⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vm.c

📁 一个类似windows
💻 C
📖 第 1 页 / 共 2 页
字号:
		JS_BC_READ_INT32 (cp + ui, se->offset);
		ui += 4;
	      }
	    break;
	  }

      /* Check if we have debugging information. */
      debug_info = NULL;
      debug_info_len = 0;
      for (sect = 0; sect < bc->num_sects; sect++)
	if (bc->sects[sect].type == JS_BCST_DEBUG)
	  {
	    debug_info = bc->sects[sect].data;
	    debug_info_len = bc->sects[sect].length;
	  }

      /* Clear error message and old exec result. */
      vm->error[0] = '\0';
      vm->exec_result.type = JS_UNDEFINED;

      PROFILING_ON ();

      /* Execute. */
      result = (*vm->dispatch_execute) (vm, bc, symtab, num_symtab_entries,
					consts_offset,
					anonymous_function_offset,
					debug_info, debug_info_len,
					NULL, NULL, 0, NULL);
    }

  PROFILING_OFF ();

  if (symtab)
    {
      for (ui = 0; ui < num_symtab_entries; ui++)
	js_free (symtab[ui].name);
      js_free (symtab);
    }

  /* Pop all error handler frames from the handler chain. */
  for (; vm->error_handler != saved_handler; vm->error_handler = handler)
    {
      handler = vm->error_handler->next;
      js_free (vm->error_handler);
    }

  /* Restore virtual machine's idea about the stack top. */
  vm->sp = saved_sp;

  return result;
}


int
js_vm_apply (JSVirtualMachine *vm, char *func_name, JSNode *func,
	     unsigned int argc, JSNode *argv)
{
  int result = 1;
  JSNode *saved_sp;
  JSErrorHandlerFrame *handler, *saved_handler;

  /* Initialize error handler. */

  saved_sp = vm->sp;
  saved_handler = vm->error_handler;

  handler = js_calloc (NULL, 1, sizeof (*handler));
  if (handler == NULL)
    {
      sprintf (vm->error, "VM: out of memory");
      return 0;
    }
  handler->next = vm->error_handler;
  vm->error_handler = handler;

  if (setjmp (vm->error_handler->error_jmp))
    {
      /* An error occurred. */
      result = 0;
    }
  else
    {
      /* Clear error message and old exec result. */
      vm->error[0] = '\0';
      vm->exec_result.type = JS_UNDEFINED;

      if (func_name)
	/* Lookup the function. */
	func = &vm->globals[js_vm_intern (vm, func_name)];

      /* Check what kind of function should be called. */
      if (func->type == JS_FUNC)
	{
	  PROFILING_ON ();

	  /* Call function. */
	  result = (*vm->dispatch_execute) (vm, NULL, NULL, 0, 0, 0,
					    NULL, 0,
					    NULL, func, argc, argv);
	}
      else if (func->type == JS_BUILTIN
	       && func->u.vbuiltin->info->global_method_proc != NULL)
	{
	  (*func->u.vbuiltin->info->global_method_proc) (
					vm,
					func->u.vbuiltin->info,
					func->u.vbuiltin->instance_context,
					&vm->exec_result,
					argv);
	}
      else
	{
	  if (func_name)
	    sprintf (vm->error, "undefined function `%s' in apply",
		     func_name);
	  else
	    sprintf (vm->error, "undefiend function in apply");

	  result = 0;
	}
    }

  PROFILING_OFF ();

  /* Pop all error handler frames from the handler chain. */
  for (; vm->error_handler != saved_handler; vm->error_handler = handler)
    {
      handler = vm->error_handler->next;
      js_free (vm->error_handler);
    }

  /* Restore virtual machine's idea about the stack top. */
  vm->sp = saved_sp;

  return result;
}


int
js_vm_call_method (JSVirtualMachine *vm, JSNode *object,
		   const char *method_name, unsigned int argc, JSNode *argv)
{
  int result = 1;
  JSNode *saved_sp;
  JSErrorHandlerFrame *handler, *saved_handler;
  JSSymbol symbol;

  /* Initialize error handler. */

  saved_sp = vm->sp;
  saved_handler = vm->error_handler;

  handler = js_calloc (NULL, 1, sizeof (*handler));
  if (handler == NULL)
    {
      sprintf (vm->error, "VM: out of memory");
      return 0;
    }
  handler->next = vm->error_handler;
  vm->error_handler = handler;

  if (setjmp (vm->error_handler->error_jmp))
    {
      /* An error occurred. */
      result = 0;
    }
  else
    {
      /* Intern the method name. */
      symbol = js_vm_intern (vm, method_name);

      /* Clear error message and old exec result. */
      vm->error[0] = '\0';
      vm->exec_result.type = JS_UNDEFINED;

      /* What kind of object was called? */

      if (object->type == JS_BUILTIN)
	{
	  if (object->u.vbuiltin->info->method_proc)
	    {
	      if ((*object->u.vbuiltin->info->method_proc) (
					vm,
					object->u.vbuiltin->info,
					object->u.vbuiltin->instance_context,
					symbol,
					&vm->exec_result, argv)
		  == JS_PROPERTY_UNKNOWN)
		{
		  sprintf (vm->error, "call_method: unknown method");
		  result = 0;
		}
	    }
	  else
	    {
	      sprintf (vm->error, "illegal builtin object for call_method");
	      result = 0;
	    }
	}
      else if (object->type == JS_OBJECT)
	{
	  JSNode method;

	  /* Fetch the method's implementation. */
	  if (js_vm_object_load_property (vm, object->u.vobject, symbol,
					  &method)
	      == JS_PROPERTY_FOUND)
	    {
	      /* The property has been defined in the object. */
	      if (method.type != JS_FUNC)
		{
		  sprintf (vm->error, "call_method: unknown method");
		  result = 0;
		}
	      else
		{
		  PROFILING_ON ();
		  result = (*vm->dispatch_execute) (vm, NULL, NULL, 0, 0, 0,
						    NULL, 0,
						    object, &method, argc,
						    argv);
		}
	    }
	  else
	    /* Let the built-in Object handle this. */
	    goto to_builtin_please;
	}
      else if (vm->prim[object->type])
	{
	  /* The primitive language types. */
	to_builtin_please:
	  if ((*vm->prim[object->type]->method_proc) (vm,
						      vm->prim[object->type],
						      object, symbol,
						      &vm->exec_result,
						      argv)
	      == JS_PROPERTY_UNKNOWN)
	    {
	      sprintf (vm->error, "call_method: unknown method");
	      result = 0;
	    }
	}
      else
	{
	  sprintf (vm->error, "illegal object for call_method");
	  result = 0;
	}
    }

  PROFILING_OFF ();

  /* Pop all error handler frames from the handler chain. */
  for (; vm->error_handler != saved_handler; vm->error_handler = handler)
    {
      handler = vm->error_handler->next;
      js_free (vm->error_handler);
    }

  /* Restore virtual machine's idea about the stack top. */
  vm->sp = saved_sp;

  return result;
}


const char *
js_vm_func_name (JSVirtualMachine *vm, void *pc)
{
  return (*vm->dispatch_func_name) (vm, pc);
}


const char *
js_vm_debug_position (JSVirtualMachine *vm, unsigned int *linenum_return)
{
  return (*vm->dispatch_debug_position) (vm, linenum_return);
}


unsigned int
js_vm_intern_with_len (JSVirtualMachine *vm, const char *name,
		       unsigned int len)
{
  JSHashBucket *b;
  unsigned int pos = js_count_hash (name, len) % JS_HASH_TABLE_SIZE;

  for (b = vm->globals_hash[pos]; b; b = b->next)
    if (strcmp (b->name, name) == 0)
      return b->u.ui;

  b = js_malloc (vm, sizeof (*b));
  b->name = js_strdup (vm, name);

  b->next = vm->globals_hash[pos];
  vm->globals_hash[pos] = b;

  /* Alloc space from the globals array. */
  if (vm->num_globals >= vm->globals_alloc)
    {
      vm->globals = js_realloc (vm, vm->globals,
				(vm->globals_alloc + 1024) * sizeof (JSNode));
      vm->globals_alloc += 1024;
    }

  /* Initialize symbol's name spaces. */
  vm->globals[vm->num_globals].type = JS_UNDEFINED;
  b->u.ui = vm->num_globals++;

  return b->u.ui;
}


const char *
js_vm_symname (JSVirtualMachine *vm, JSSymbol sym)
{
  int i;
  JSHashBucket *b;

  for (i = 0; i < JS_HASH_TABLE_SIZE; i++)
    for (b = vm->globals_hash[i]; b; b = b->next)
      if (b->u.ui == sym)
	return b->name;

  return "???";
}


void
js_vm_error (JSVirtualMachine *vm)
{
  const char *file;
  unsigned int ln;
  char error[1024];

  file = js_vm_debug_position (vm, &ln);
  if (file)
    {
      sprintf (error, "%s:%u: %s", file, ln, vm->error);
      strcpy (vm->error, error);
    }

  if (vm->stacktrace_on_error)
    {
      sprintf (error, "VM: error: %s%s", vm->error,
	       JS_HOST_LINE_BREAK);
      js_iostream_write (vm->s_stderr, error, strlen (error));

      js_vm_stacktrace (vm, (unsigned int) -1);
    }

  if (vm->error_handler->sp)
    /*
     * We are jumping to a catch-block.  Format our error message to
     * the `thrown' node.
     */
    js_vm_make_string (vm, &vm->error_handler->thrown,
		       vm->error, strlen (vm->error));

  longjmp (vm->error_handler->error_jmp, 1);

  /* NOTREACHED (I hope). */

  sprintf (error, "VM: no valid error handler initialized%s",
	   JS_HOST_LINE_BREAK);
  js_iostream_write (vm->s_stderr, error, strlen (error));
  js_iostream_flush (vm->s_stderr);

  abort ();
}

/* Delete proc for garbaged built-in objects. */
static void
destroy_builtin (void *ptr)
{
  JSBuiltin *bi = ptr;

  if (bi->info->delete_proc)
    (*bi->info->delete_proc) (bi->info, bi->instance_context);
}

/* Delete proc for garbaged built-in info. */
static void
destroy_builtin_info (void *ptr)
{
  JSBuiltinInfo *i = ptr;

  if (i->obj_context_delete)
    (*i->obj_context_delete) (i->obj_context);
}


JSBuiltinInfo *
js_vm_builtin_info_create (JSVirtualMachine *vm)
{
  JSNode prototype;
  JSBuiltinInfo *i = js_vm_alloc_destroyable (vm, sizeof (*i));

  i->destroy = destroy_builtin_info;
  i->prototype = js_vm_object_new (vm);

  /*
   * Set the __proto__ property to null.  We have no prototype object
   * above us.
   */
  prototype.type = JS_NULL;
  js_vm_object_store_property (vm, i->prototype, vm->syms.s___proto__,
			       &prototype);

  return i;
}


void
js_vm_builtin_create (JSVirtualMachine *vm, JSNode *result,
		      JSBuiltinInfo *info, void *instance_context)
{
  result->type = JS_BUILTIN;
  result->u.vbuiltin = js_vm_alloc_destroyable (vm, sizeof (JSBuiltin));
  result->u.vbuiltin->destroy = destroy_builtin;
  result->u.vbuiltin->info = info;

  if (instance_context)
    {
      JSNode prototype;

      result->u.vbuiltin->instance_context = instance_context;
      result->u.vbuiltin->prototype = js_vm_object_new (vm);

      /* Set the __proto__ chain. */

      prototype.type = JS_OBJECT;
      prototype.u.vobject = info->prototype;

      js_vm_object_store_property (vm, result->u.vbuiltin->prototype,
				   vm->syms.s___proto__, &prototype);
    }
}


/*
 * Static functions.
 */

extern void js_builtin_core (JSVirtualMachine *vm);

extern void js_builtin_Array (JSVirtualMachine *vm);
extern void js_builtin_Boolean (JSVirtualMachine *vm);
extern void js_builtin_Function (JSVirtualMachine *vm);
extern void js_builtin_Number (JSVirtualMachine *vm);
extern void js_builtin_Object (JSVirtualMachine *vm);
extern void js_builtin_String (JSVirtualMachine *vm);
extern void js_builtin_File (JSVirtualMachine *vm);
extern void js_builtin_System (PKJS kjs);

extern void js_builtin_RegExp (JSVirtualMachine *vm);
extern void js_builtin_VM (JSVirtualMachine *vm);


static void
intern_builtins (PKJS kjs)
{
  JSVirtualMachine *vm = kjs->vm;
  /*
   * The initialization order is significant.  The RegExp object must be
   * initialized before String.
   */

  /* The core global methods. */
  js_builtin_core (vm);

  js_builtin_RegExp (vm);
  js_builtin_VM (vm);

  /* Language objects. */
  js_builtin_Array (vm);
  js_builtin_Boolean (vm);
  js_builtin_Function (vm);
  js_builtin_String (vm);
  js_builtin_Number (vm);
  js_builtin_Object (vm);
  js_builtin_File (vm);
  js_builtin_System (kjs);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -