Пример #1
0
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) {
		// CHANGE alloc times to 16
		vm->globals = js_realloc(vm, vm->globals, (vm->globals_alloc + 16) * sizeof(JSNode));
		vm->globals_alloc += 16;
	}

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

	return b->u.ui;
}
Пример #2
0
int
js_vm_switch0_exec (JSVirtualMachine *vm, JSByteCode *bc,
                    JSSymtabEntry *symtab,
                    unsigned int num_symtab_entries,
                    unsigned int consts_offset,
                    unsigned int anonymous_function_offset,
                    /*unsigned char *debug_info, unsigned int debug_info_len,*/
                    JSNode *object, JSNode *func,
                    unsigned int argc, JSNode *argv)
{
  int i;
  unsigned int ui;
  Function *global_f = NULL;
  Function *f;
  unsigned char *code = NULL;
  char buf[512];

  if (bc)
    {
      /* Executing byte-code. */

      /* Find the code section. */
      for (i = 0; i < bc->num_sects; i++)
        if (bc->sects[i].type == JS_BCST_CODE)
          code = bc->sects[i].data;
      assert (code != NULL);

      /* Enter all functions to the known functions of the VM. */
      for (i = 0; i < num_symtab_entries; i++)
        {
          /* Need one function. */
          f = js_vm_alloc_destroyable (vm, sizeof (*f));
          f->destroy = function_destroy;
          f->name = js_strdup (vm, symtab[i].name);

          f->length = symtab[i + 1].offset - symtab[i].offset + 1;
          f->code = js_malloc (vm, f->length);
          memcpy (f->code, code + symtab[i].offset, f->length - 1);
          f->code[f->length - 1] = 1; /* op `done' */

          /* Link the code to our environment. */
          link_code (vm, f->code, f->length, consts_offset);

          if (strcmp (symtab[i].name, JS_GLOBAL_NAME) == 0)
            global_f = f;
          else
            {
              int is_anonymous = 0;

              /* Check for the anonymous function. */
              if (symtab[i].name[0] == '.' && symtab[i].name[1] == 'F'
                  && symtab[i].name[2] == ':')
                is_anonymous = 1;

              if (vm->verbose > 3)
                {
                  sprintf_P (buf, vmswt0_string_0,
                             symtab[i].name, symtab[i].offset,
                             symtab[i + 1].offset - symtab[i].offset);
                  if (is_anonymous)
                    sprintf_P (buf + strlen (buf), vmswt0_string_1,
                               anonymous_function_offset);
                  strcat (buf, JS_HOST_LINE_BREAK);
                  //js_iostream_write (vm->s_stderr, buf, strlen (buf));
                }

              if (is_anonymous)
                {
                  sprintf (buf, ".F:%u",
                           (unsigned int) atoi (symtab[i].name + 3)
                           + anonymous_function_offset);
                  ui = js_vm_intern (vm, buf);
                }
              else
                ui = js_vm_intern (vm, symtab[i].name);

              vm->globals[ui].type = JS_FUNC;
              vm->globals[ui].u.vfunction = js_vm_make_function (vm, f);
            }
        }
    }
  else
    {
      /* Applying arguments to function. */
      if (func->type != JS_FUNC)
        {
          sprintf_P (vm->error, vmswt0_string_2);
          return 0;
        }

      if (vm->verbose > 1)
        {
          sprintf_P (buf, vmswt0_string_3, JS_HOST_LINE_BREAK);
          //js_iostream_write (vm->s_stderr, buf, strlen (buf));
        }
      f = func->u.vfunction->implementation;

      execute_code (vm, object, f, argc, argv);
    }

  if (global_f)
    {
      if (vm->verbose > 1)
        {
          sprintf_P (buf, vmswt0_string_4, global_f->name, JS_HOST_LINE_BREAK);
          //js_iostream_write (vm->s_stderr, buf, strlen (buf));
        }

      /* Execute. */
      execute_code (vm, NULL, global_f, 0, NULL);
    }

  return 1;
}
Пример #3
0
int js_vm_execute(JSVirtualMachine * vm, JSByteCode * bc)
{
	int i, sect;
	unsigned int ui;
	unsigned char *cp;
	unsigned int consts_offset;
	char buf[256];
	JSSymtabEntry *symtab = NULL;
	unsigned int num_symtab_entries = 0;
	unsigned int code_len = 0;
	JSNode *saved_sp;
	JSErrorHandlerFrame *handler, *saved_handler;
	int result = 1;
#ifdef JS_RUNTIME_DEBUG
	unsigned char *debug_info;
	unsigned int debug_info_len;
#endif
	unsigned int anonymous_function_offset;

	/* We need a toplevel over the whole function. */

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

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

	if (setjmp(vm->error_handler->error_jmp)) {
		/* Ok, we had an error down there somewhere. */
		if(vm->error_handler->thrown.type == JS_INTEGER) {
			result = vm->error_handler->thrown.u.vinteger;
		} else {
			result = 0;
		}
	} else {
		/* The main stuffs for the execute. */

		/* Process constants. */
		consts_offset = vm->num_consts;
		anonymous_function_offset = vm->anonymous_function_next_id;

		for (sect = 0; sect < bc->num_sects; sect++)
			if (bc->sects[sect].type == JS_BCST_CONSTANTS) {
				cp = bc->sects[sect].data;

				for (ui = 0; ui < bc->sects[sect].length;) {
					JSNode *c;

					/* Check that we still have space for this constant. */
					if (vm->num_consts >= vm->consts_alloc) {
						// CHANGE alloc times to 16
						vm->consts = js_realloc(vm, vm->consts, (vm->consts_alloc + 16)
												* sizeof(JSNode));
						vm->consts_alloc += 16;
					}
					c = &vm->consts[vm->num_consts++];

					/*  Process this constant. */
					c->type = (JSNodeType) cp[ui++];
					switch (c->type) {
					case JS_NULL:
						break;

					case JS_BOOLEAN:
						c->u.vboolean = cp[ui++];
						break;

					case JS_STRING:
						c->u.vstring = js_vm_alloc(vm, sizeof(*c->u.vstring));
						c->u.vstring->staticp = 1;
						c->u.vstring->prototype = NULL;

						JS_BC_READ_INT32(cp + ui, c->u.vstring->len);
						ui += 4;

						c->u.vstring->data = js_malloc(vm, c->u.vstring->len + 1);
						memcpy(c->u.vstring->data, cp + ui, c->u.vstring->len);
						c->u.vstring->data[c->u.vstring->len] = '\0';

						ui += c->u.vstring->len;
						break;

					case JS_INTEGER:
						JS_BC_READ_INT32(cp + ui, c->u.vinteger);
						ui += 4;
						break;

					case JS_FLOAT:
						memcpy(&c->u.vfloat, cp + ui, sizeof(JSFloat));
						ui += sizeof(JSFloat);
						break;

					case JS_SYMBOL:
						for (i = 0; cp[ui]; ui++, i++)
							buf[i] = cp[ui];
						buf[i] = '\0';

						/* Eat the trailing '\0' from the data. */
						ui++;

						if (buf[0] == '.' && buf[1] == 'F' && buf[2] == ':')
							//sprintf(buf + 3, "%u", vm->anonymous_function_next_id++);
							vm->anonymous_function_next_id++;

						/* Intern symbol. */
						c->u.vsymbol = js_vm_intern(vm, buf);
						break;
#if 0
					case JS_BUILTIN:
						/* Regular expression. */
						{
						   unsigned char flags;
						   unsigned int length;

						   flags = cp[ui++];

						   JS_BC_READ_INT32 (cp + ui, length);
						   ui += 4;

						   js_builtin_RegExp_new (vm, cp + ui, length, flags, 1,
						   NULL, c);
						   ui += length;
						}
						break;
#endif
					case JS_NAN:
						/* Nothing here. */
						break;

					default:
					case JS_IPTR:
#ifdef JS_RUNTIME_WARNING
						sprintf(buf,
								"js_vm_execute(): unknown constant type %d%s",
								c->type, JS_HOST_LINE_BREAK);

#ifdef JS_IOSTREAM
				        js_iostream_write(vm->s_stderr, buf, strlen(buf));
        				js_iostream_flush(vm->s_stderr);
#else
						fwrite(buf, strlen(buf), 1, stderr);
#endif
#endif

						abort();
						break;
					}
				}

				/* All done with the constants. */
				break;
			}

		/* Check how long the code section is. */
		for (sect = 0; sect < bc->num_sects; sect++)
			if (bc->sects[sect].type == JS_BCST_CODE) {
				code_len = bc->sects[sect].length;
				break;
			}

		/* Process symbol table. */
		for (sect = 0; sect < bc->num_sects; sect++)
			if (bc->sects[sect].type == JS_BCST_SYMTAB) {
				JSSymtabEntry *se;
				char buf[257];

				cp = bc->sects[sect].data;

				/* The number of symbols. */
				JS_BC_READ_INT32(cp, num_symtab_entries);

				symtab = js_calloc(vm, num_symtab_entries + 1, sizeof(*symtab));

				/* Make the terminator by hand. */
				symtab[num_symtab_entries].offset = code_len;

				/* Enter symbols. */
				se = symtab;
				for (ui = 4; ui < bc->sects[sect].length; se++) {
					for (i = 0; cp[ui]; ui++, i++)
						buf[i] = cp[ui];
					buf[i] = '\0';

					se->name = js_strdup(vm, buf);
					ui++;

					JS_BC_READ_INT32(cp + ui, se->offset);
					ui += 4;
				}
				break;
			}

		/* Check if we have debugging information. */
#ifdef JS_RUNTIME_DEBUG
		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;
			}
#endif
		/* Clear error message and old exec result. */
#ifdef JS_RUNTIME_WARNING
		vm->error[0] = '\0';
#endif
		vm->exec_result.type = JS_UNDEFINED;

		JS_PROFILING_ON();

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

	JS_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;
}
Пример #4
0
int
js_vm_switch_exec (JSVirtualMachine *vm, JSByteCode *bc, JSSymtabEntry *symtab,
		   unsigned int num_symtab_entries,
		   unsigned int consts_offset,
		   unsigned char *debug_info, unsigned int debug_info_len,
		   char *func_name, JSNode *func,
		   unsigned int argc, JSNode *argv)
{
  int i;
  unsigned int ui;
  Function *global_f = NULL;
  Function *f;
  unsigned char *code = NULL;

  if (bc)
    {
      /* Executing byte-code. */

      /* Find the code section. */
      for (i = 0; i < bc->num_sects; i++)
	if (bc->sects[i].type == JS_BCST_CODE)
	  code = bc->sects[i].data;
      assert (code != NULL);

      /* Enter all functions to the known functions of the VM. */
      for (i = 0; i < num_symtab_entries; i++)
	{
	  /* Link the code to our environment. */
	  f = link_code (vm, code + symtab[i].offset,
			 symtab[i + 1].offset - symtab[i].offset,
			 consts_offset);
	  f->name = js_strdup (vm, symtab[i].name);

	  if (strcmp (symtab[i].name, JS_GLOBAL_NAME) == 0)
	    global_f = f;
	  else
	    {
	      if (vm->verbose > 3)
		printf ("VM: link: %s(): start=%d, length=%d\n",
			symtab[i].name, symtab[i].offset,
			symtab[i + 1].offset - symtab[i].offset);
	      ui = js_vm_intern (vm, symtab[i].name);

	      vm->globals[ui].type = JS_FUNC;
	      vm->globals[ui].u.vfunction = js_vm_make_function (vm, f);
	    }
	}
    }
  else
    {
      JSNode *n;

      /* Applying arguments to function. */

      if (func_name)
	{
	  /* Lookup function. */
	  JSSymbol sym;

	  sym = js_vm_intern (vm, func_name);
	  n = &vm->globals[sym];
	  if (n->type != JS_FUNC)
	    {
	      sprintf (vm->error, "undefined function `%s' in apply",
		       func_name);
	      return 0;
	    }

	  if (vm->verbose > 1)
	    printf ("VM: calling %s()\n", func_name);
	}
      else
	{
	  /* Use the function the caller gave us. */
	  n = func;
	  if (n->type != JS_FUNC)
	    {
	      sprintf (vm->error, "illegal function in apply");
	      return 0;
	    }

	  if (vm->verbose > 1)
	    printf ("VM: calling function\n");
	}
      f = n->u.vfunction->implementation;

      execute_code (vm, f, argc, argv);
    }

  if (global_f)
    {
      if (vm->verbose > 1)
	printf ("VM: exec: %s\n", global_f->name);

      /* Execute. */
      execute_code (vm, global_f, 0, NULL);
    }

  return 1;
}