$(NXT_BUILDDIR)/njs_regexp.o \
$(NXT_BUILDDIR)/njs_extern.o \
$(NXT_BUILDDIR)/njs_variable.o \
- $(NXT_BUILDDIR)/njs_shared.o \
+ $(NXT_BUILDDIR)/njs_builtin.o \
$(NXT_BUILDDIR)/njs_lexer.o \
$(NXT_BUILDDIR)/njs_lexer_keyword.o \
$(NXT_BUILDDIR)/njs_nonrecursive_parser.o \
$(NXT_BUILDDIR)/njs_regexp.o \
$(NXT_BUILDDIR)/njs_extern.o \
$(NXT_BUILDDIR)/njs_variable.o \
- $(NXT_BUILDDIR)/njs_shared.o \
+ $(NXT_BUILDDIR)/njs_builtin.o \
$(NXT_BUILDDIR)/njs_lexer.o \
$(NXT_BUILDDIR)/njs_lexer_keyword.o \
$(NXT_BUILDDIR)/njs_nonrecursive_parser.o \
-I$(NXT_LIB) -Injs \
njs/njs_variable.c
-$(NXT_BUILDDIR)/njs_shared.o: \
+$(NXT_BUILDDIR)/njs_builtin.o: \
$(NXT_BUILDDIR)/libnxt.a \
njs/njscript.h \
njs/njs_vm.h \
njs/njs_object.h \
njs/njs_array.h \
njs/njs_function.h \
+ njs/njs_regexp.h \
njs/njs_parser.h \
- njs/njs_shared.c \
+ njs/njs_builtin.c \
- $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_shared.o $(NXT_CFLAGS) \
+ $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_builtin.o $(NXT_CFLAGS) \
-I$(NXT_LIB) -Injs \
- njs/njs_shared.c
+ njs/njs_builtin.c
$(NXT_BUILDDIR)/njs_lexer.o: \
$(NXT_BUILDDIR)/libnxt.a \
uint32_t size;
njs_array_t *array;
- array = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
- sizeof(njs_array_t));
-
+ array = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_array_t));
if (nxt_slow_path(array == NULL)) {
return NULL;
}
njs_ret_t
-njs_array_function(njs_vm_t *vm, njs_param_t *param)
+njs_array_constructor(njs_vm_t *vm, njs_param_t *param)
{
double num;
uint32_t size;
}
-static const njs_object_prop_t njs_array_function_properties[] =
+static const njs_object_prop_t njs_array_constructor_properties[] =
{
/* Array.name == "Array". */
{ njs_string("Array"),
NJS_PROPERTY, 0, 0, 0, },
/* Array.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_array_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_array_function_properties,
- nxt_nitems(njs_array_function_properties));
-}
+const njs_object_init_t njs_array_constructor_init = {
+ njs_array_constructor_properties,
+ nxt_nitems(njs_array_constructor_properties),
+};
static njs_ret_t
};
-nxt_int_t
-njs_array_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_array_prototype_properties,
- nxt_nitems(njs_array_prototype_properties));
-}
+const njs_object_init_t njs_array_prototype_init = {
+ njs_array_prototype_properties,
+ nxt_nitems(njs_array_prototype_properties),
+};
njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare);
njs_ret_t njs_array_realloc(njs_vm_t *vm, njs_array_t *array, uint32_t prepend,
uint32_t size);
-njs_ret_t njs_array_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_array_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_array_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_array_constructor(njs_vm_t *vm, njs_param_t *param);
+
+extern const njs_object_init_t njs_array_constructor_init;
+extern const njs_object_init_t njs_array_prototype_init;
#endif /* _NJS_ARRAY_H_INCLUDED_ */
njs_ret_t
-njs_boolean_function(njs_vm_t *vm, njs_param_t *param)
+njs_boolean_constructor(njs_vm_t *vm, njs_param_t *param)
{
njs_object_t *object;
const njs_value_t *value;
}
if (vm->frame->ctor) {
- /* value->type is the same as prototype offset. */
object = njs_object_value_alloc(vm, value, value->type);
if (nxt_slow_path(object == NULL)) {
return NXT_ERROR;
}
-static const njs_object_prop_t njs_boolean_function_properties[] =
+static const njs_object_prop_t njs_boolean_constructor_properties[] =
{
/* Boolean.name == "Boolean". */
{ njs_string("Boolean"),
NJS_PROPERTY, 0, 0, 0, },
/* Boolean.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_boolean_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_boolean_function_properties,
- nxt_nitems(njs_boolean_function_properties));
-}
+const njs_object_init_t njs_boolean_constructor_init = {
+ njs_boolean_constructor_properties,
+ nxt_nitems(njs_boolean_constructor_properties),
+};
static njs_ret_t
};
-nxt_int_t
-njs_boolean_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_boolean_prototype_properties,
- nxt_nitems(njs_boolean_prototype_properties));
-}
+const njs_object_init_t njs_boolean_prototype_init = {
+ njs_boolean_prototype_properties,
+ nxt_nitems(njs_boolean_prototype_properties),
+};
#define _NJS_BOOLEAN_H_INCLUDED_
-njs_ret_t njs_boolean_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_boolean_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_boolean_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_boolean_constructor(njs_vm_t *vm, njs_param_t *param);
+
+extern const njs_object_init_t njs_boolean_constructor_init;
+extern const njs_object_init_t njs_boolean_prototype_init;
#endif /* _NJS_BOOLEAN_H_INCLUDED_ */
--- /dev/null
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_boolean.h>
+#include <njs_number.h>
+#include <njs_string.h>
+#include <njs_object.h>
+#include <njs_array.h>
+#include <njs_function.h>
+#include <njs_regexp.h>
+#include <string.h>
+
+
+nxt_int_t
+njs_builtin_objects_create(njs_vm_t *vm)
+{
+ nxt_int_t ret;
+ nxt_uint_t i;
+ njs_object_t *prototypes;
+ njs_function_t *functions;
+
+ static const njs_object_init_t *prototype_init[] = {
+ &njs_object_prototype_init,
+ &njs_array_prototype_init,
+ &njs_boolean_prototype_init,
+ &njs_number_prototype_init,
+ &njs_string_prototype_init,
+ &njs_function_prototype_init,
+ &njs_regexp_prototype_init,
+ };
+
+ static const njs_object_init_t *function_init[] = {
+ &njs_object_constructor_init,
+ &njs_array_constructor_init,
+ &njs_boolean_constructor_init,
+ &njs_number_constructor_init,
+ &njs_string_constructor_init,
+ &njs_function_constructor_init,
+ &njs_regexp_constructor_init,
+
+ &njs_eval_function_init,
+ };
+
+ static const njs_native_t native_functions[] = {
+ njs_object_constructor,
+ njs_array_constructor,
+ njs_boolean_constructor,
+ njs_number_constructor,
+ njs_string_constructor,
+ njs_function_constructor,
+ njs_regexp_constructor,
+
+ njs_eval_function,
+ };
+
+ static const njs_object_prop_t null_proto_property = {
+ njs_value(NJS_NULL, 0, 0.0),
+ njs_string("__proto__"),
+ NJS_WHITEOUT, 0, 0, 0,
+ };
+
+ ret = njs_object_hash_create(vm, &vm->shared->null_proto_hash,
+ &null_proto_property, 1);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ prototypes = vm->shared->prototypes;
+
+ for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
+ /* TODO: shared hash: prototype & constructor getters, methods */
+
+ ret = njs_object_hash_create(vm, &prototypes[i].shared_hash,
+ prototype_init[i]->properties,
+ prototype_init[i]->items);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+
+ functions = vm->shared->functions;
+
+ for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+ functions[i].native = 1;
+ functions[i].args_offset = 1;
+ functions[i].code.native = native_functions[i];
+
+ ret = njs_object_hash_create(vm, &functions[i].object.shared_hash,
+ function_init[i]->properties,
+ function_init[i]->items);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+
+ /* TODO: create function shared hash: prototype+contructor getter */
+
+ return NXT_OK;
+}
+
+
+/*
+ * Object(),
+ * Object.__proto__ -> Function_Prototype,
+ * Object_Prototype.__proto__ -> null,
+ * the null value is handled by njs_object_prototype_get_proto(),
+ *
+ * Array(),
+ * Array.__proto__ -> Function_Prototype,
+ * Array_Prototype.__proto__ -> Object_Prototype,
+ *
+ * Boolean(),
+ * Boolean.__proto__ -> Function_Prototype,
+ * Boolean_Prototype.__proto__ -> Object_Prototype,
+ *
+ * Number(),
+ * Number.__proto__ -> Function_Prototype,
+ * Number_Prototype.__proto__ -> Object_Prototype,
+ *
+ * String(),
+ * String.__proto__ -> Function_Prototype,
+ * String_Prototype.__proto__ -> Object_Prototype,
+ *
+ * Function(),
+ * Function.__proto__ -> Function_Prototype,
+ * Function_Prototype.__proto__ -> Object_Prototype,
+ *
+ * RegExp(),
+ * RegExp.__proto__ -> Function_Prototype,
+ * RegExp_Prototype.__proto__ -> Object_Prototype,
+ *
+ * eval(),
+ * eval.__proto__ -> Function_Prototype.
+ */
+
+nxt_int_t
+njs_builtin_objects_clone(njs_vm_t *vm)
+{
+ size_t size;
+ nxt_uint_t i;
+ njs_value_t *values;
+ njs_object_t *function_prototype;
+
+ size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t)
+ + NJS_FUNCTION_MAX * sizeof(njs_function_t);
+
+ memcpy(vm->prototypes, vm->shared->prototypes, size);
+
+ for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
+ vm->prototypes[i].__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ }
+
+ function_prototype = &vm->prototypes[NJS_FUNCTION_FUNCTION];
+ values = vm->scopes[NJS_SCOPE_GLOBAL];
+
+ for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+ values[i].type = NJS_FUNCTION;
+ values[i].data.truth = 1;
+ values[i].data.u.function = &vm->functions[i];
+ vm->functions[i].object.__proto__ = function_prototype;
+ }
+
+ return NXT_OK;
+}
njs_function_t *func;
njs_function_script_t *script;
- func = nxt_mem_cache_zalign(vm->mem_cache_pool, sizeof(njs_value_t),
- sizeof(njs_function_t));
+ func = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
if (nxt_fast_path(func != NULL)) {
func->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
njs_ret_t
-njs_function_function(njs_vm_t *vm, njs_param_t *param)
+njs_function_constructor(njs_vm_t *vm, njs_param_t *param)
{
return NXT_ERROR;
}
}
-static const njs_object_prop_t njs_function_function_properties[] =
+static const njs_object_prop_t njs_function_constructor_properties[] =
{
/* Function.name == "Function". */
{ njs_string("Function"),
NJS_PROPERTY, 0, 0, 0, },
/* Function.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_function_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_function_function_properties,
- nxt_nitems(njs_function_function_properties));
-}
+const njs_object_init_t njs_function_constructor_init = {
+ njs_function_constructor_properties,
+ nxt_nitems(njs_function_constructor_properties),
+};
static njs_ret_t
};
-nxt_int_t
-njs_function_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_function_prototype_properties,
- nxt_nitems(njs_function_prototype_properties));
-}
+const njs_object_init_t njs_function_prototype_init = {
+ njs_function_prototype_properties,
+ nxt_nitems(njs_function_prototype_properties),
+};
njs_ret_t
};
-nxt_int_t
-njs_eval_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_eval_function_properties,
- nxt_nitems(njs_eval_function_properties));
-}
+const njs_object_init_t njs_eval_function_init = {
+ njs_eval_function_properties,
+ nxt_nitems(njs_eval_function_properties),
+};
};
-struct njs_function_s {
- njs_object_t object;
-
-#if (NXT_64BIT)
- uint32_t native;
- uint32_t args_offset;
-#else
- uint8_t native;
- uint16_t args_offset;
-#endif
-
- union {
- njs_function_script_t *script;
- njs_native_t native;
- } code;
-
- njs_value_t *args;
-};
-
-
/* The frame size must be aligned to njs_value_t. */
#define NJS_NATIVE_FRAME_SIZE \
nxt_align_size(sizeof(njs_native_frame_t), sizeof(njs_value_t))
njs_function_t *njs_function_alloc(njs_vm_t *vm);
-njs_ret_t njs_function_function(njs_vm_t *vm, njs_param_t *param);
+njs_ret_t njs_function_constructor(njs_vm_t *vm, njs_param_t *param);
njs_ret_t njs_function_apply(njs_vm_t *vm, njs_value_t *name,
njs_param_t *param);
njs_value_t *njs_vmcode_native_frame(njs_vm_t *vm, njs_value_t *method,
njs_param_t *param, nxt_bool_t ctor);
njs_ret_t njs_function_call(njs_vm_t *vm, njs_function_t *func,
njs_index_t retval);
-nxt_int_t njs_function_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_function_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+
+extern const njs_object_init_t njs_function_constructor_init;
+extern const njs_object_init_t njs_function_prototype_init;
njs_ret_t njs_eval_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_eval_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+
+extern const njs_object_init_t njs_eval_function_init;
#endif /* _NJS_FUNCTION_H_INCLUDED_ */
return njs_generate_regexp(vm, parser, node);
case NJS_TOKEN_THIS:
- case NJS_TOKEN_OBJECT_FUNCTION:
- case NJS_TOKEN_ARRAY_FUNCTION:
- case NJS_TOKEN_NUMBER_FUNCTION:
- case NJS_TOKEN_BOOLEAN_FUNCTION:
- case NJS_TOKEN_STRING_FUNCTION:
- case NJS_TOKEN_FUNCTION_FUNCTION:
- case NJS_TOKEN_REGEXP_FUNCTION:
+ case NJS_TOKEN_OBJECT_CONSTRUCTOR:
+ case NJS_TOKEN_ARRAY_CONSTRUCTOR:
+ case NJS_TOKEN_NUMBER_CONSTRUCTOR:
+ case NJS_TOKEN_BOOLEAN_CONSTRUCTOR:
+ case NJS_TOKEN_STRING_CONSTRUCTOR:
+ case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
+ case NJS_TOKEN_REGEXP_CONSTRUCTOR:
case NJS_TOKEN_EVAL:
case NJS_TOKEN_EXTERNAL:
return NXT_OK;
/* Builtin functions. */
- { nxt_string("Object"), NJS_TOKEN_OBJECT_FUNCTION, 0 },
- { nxt_string("Array"), NJS_TOKEN_ARRAY_FUNCTION, 0 },
- { nxt_string("Boolean"), NJS_TOKEN_BOOLEAN_FUNCTION, 0 },
- { nxt_string("Number"), NJS_TOKEN_NUMBER_FUNCTION, 0 },
- { nxt_string("String"), NJS_TOKEN_STRING_FUNCTION, 0 },
- { nxt_string("Function"), NJS_TOKEN_FUNCTION_FUNCTION, 0 },
- { nxt_string("RegExp"), NJS_TOKEN_REGEXP_FUNCTION, 0 },
+ { nxt_string("Object"), NJS_TOKEN_OBJECT_CONSTRUCTOR, 0 },
+ { nxt_string("Array"), NJS_TOKEN_ARRAY_CONSTRUCTOR, 0 },
+ { nxt_string("Boolean"), NJS_TOKEN_BOOLEAN_CONSTRUCTOR, 0 },
+ { nxt_string("Number"), NJS_TOKEN_NUMBER_CONSTRUCTOR, 0 },
+ { nxt_string("String"), NJS_TOKEN_STRING_CONSTRUCTOR, 0 },
+ { nxt_string("Function"), NJS_TOKEN_FUNCTION_CONSTRUCTOR, 0 },
+ { nxt_string("RegExp"), NJS_TOKEN_REGEXP_CONSTRUCTOR, 0 },
{ nxt_string("eval"), NJS_TOKEN_EVAL, 0 },
/* Reserved words. */
njs_ret_t
-njs_number_function(njs_vm_t *vm, njs_param_t *param)
+njs_number_constructor(njs_vm_t *vm, njs_param_t *param)
{
njs_object_t *object;
const njs_value_t *value;
}
if (vm->frame->ctor) {
- /* value->type is the same as prototype offset. */
object = njs_object_value_alloc(vm, value, value->type);
if (nxt_slow_path(object == NULL)) {
return NXT_ERROR;
}
-static const njs_object_prop_t njs_number_function_properties[] =
+static const njs_object_prop_t njs_number_constructor_properties[] =
{
/* Number.name == "Number". */
{ njs_string("Number"),
NJS_PROPERTY, 0, 0, 0, },
/* Number.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_number_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_number_function_properties,
- nxt_nitems(njs_number_function_properties));
-}
+const njs_object_init_t njs_number_constructor_init = {
+ njs_number_constructor_properties,
+ nxt_nitems(njs_number_constructor_properties),
+};
static njs_ret_t
};
-nxt_int_t
-njs_number_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_number_prototype_properties,
- nxt_nitems(njs_number_prototype_properties));
-}
+const njs_object_init_t njs_number_prototype_init = {
+ njs_number_prototype_properties,
+ nxt_nitems(njs_number_prototype_properties),
+};
int64_t njs_hex_number_parse(u_char *p, u_char *end);
njs_ret_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
const njs_value_t *number);
-njs_ret_t njs_number_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_number_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_number_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_number_constructor(njs_vm_t *vm, njs_param_t *param);
+
+extern const njs_object_init_t njs_number_constructor_init;
+extern const njs_object_init_t njs_number_prototype_init;
#endif /* _NJS_NUMBER_H_INCLUDED_ */
static nxt_int_t njs_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
-static nxt_int_t njs_object_null_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
nxt_noinline njs_object_t *
njs_object_alloc(njs_vm_t *vm)
{
- njs_object_t *obj;
+ njs_object_t *object;
- obj = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
- sizeof(njs_object_t));
+ object = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_t));
- if (nxt_fast_path(obj != NULL)) {
- nxt_lvlhsh_init(&obj->hash);
- nxt_lvlhsh_init(&obj->shared_hash);
- obj->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+ if (nxt_fast_path(object != NULL)) {
+ nxt_lvlhsh_init(&object->hash);
+ nxt_lvlhsh_init(&object->shared_hash);
+ object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
}
- return obj;
+ return object;
}
nxt_noinline njs_object_t *
-njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
- nxt_uint_t prototype)
+njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value, nxt_uint_t type)
{
- njs_object_value_t *obj;
+ nxt_uint_t index;
+ njs_object_value_t *ov;
+
+ ov = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_value_t));
+
+ if (nxt_fast_path(ov != NULL)) {
+ nxt_lvlhsh_init(&ov->object.hash);
+ nxt_lvlhsh_init(&ov->object.shared_hash);
- obj = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
- sizeof(njs_object_value_t));
+ index = njs_primitive_prototype_index(type);
+ ov->object.__proto__ = &vm->prototypes[index];
- if (nxt_fast_path(obj != NULL)) {
- nxt_lvlhsh_init(&obj->object.hash);
- nxt_lvlhsh_init(&obj->object.shared_hash);
- obj->object.__proto__ = &vm->prototypes[prototype];
- obj->value = *value;
+ ov->value = *value;
}
- return &obj->object;
+ return &ov->object;
}
nxt_noinline njs_object_prop_t *
-njs_object_property(njs_vm_t *vm, njs_object_t *obj, nxt_lvlhsh_query_t *lhq)
+njs_object_property(njs_vm_t *vm, njs_object_t *object, nxt_lvlhsh_query_t *lhq)
{
nxt_int_t ret;
lhq->proto = &njs_object_hash_proto;
do {
- ret = nxt_lvlhsh_find(&obj->hash, lhq);
+ ret = nxt_lvlhsh_find(&object->hash, lhq);
if (nxt_fast_path(ret == NXT_OK)) {
return lhq->value;
}
- ret = nxt_lvlhsh_find(&obj->shared_hash, lhq);
+ ret = nxt_lvlhsh_find(&object->shared_hash, lhq);
if (nxt_fast_path(ret == NXT_OK)) {
return lhq->value;
}
- obj = obj->__proto__;
+ object = object->__proto__;
- } while (obj != NULL);
+ } while (object != NULL);
vm->exception = &njs_exception_type_error;
njs_ret_t
-njs_object_function(njs_vm_t *vm, njs_param_t *param)
+njs_object_constructor(njs_vm_t *vm, njs_param_t *param)
{
nxt_uint_t type;
njs_value_t *value;
njs_object_create(njs_vm_t *vm, njs_param_t *param)
{
njs_value_t *args;
- njs_object_t *obj;
-
- /* STUB: move to shared create to avoid threads locks. */
- static nxt_lvlhsh_t njs_null_proto_shared_hash;
+ njs_object_t *object;
if (param->nargs != 0) {
args = param->args;
if (njs_is_object(&args[0]) || njs_is_null(&args[0])) {
- obj = njs_object_alloc(vm);
- if (nxt_slow_path(obj == NULL)) {
+ object = njs_object_alloc(vm);
+ if (nxt_slow_path(object == NULL)) {
return NXT_ERROR;
}
- if (njs_is_null(&args[0])) {
- if (nxt_lvlhsh_is_empty(&njs_null_proto_shared_hash)) {
- /* STUB */
- njs_object_null_hash(vm, &njs_null_proto_shared_hash);
- }
-
- obj->shared_hash = njs_null_proto_shared_hash;
- obj->__proto__ = NULL;
+ if (!njs_is_null(&args[0])) {
+ /* GC */
+ object->__proto__ = args[0].data.u.object;
} else {
- /* GC */
- obj->__proto__ = args[0].data.u.object;
+ object->shared_hash = vm->shared->null_proto_hash;
+ object->__proto__ = NULL;
}
- vm->retval.data.u.object = obj;
+ vm->retval.data.u.object = object;
vm->retval.type = NJS_OBJECT;
vm->retval.data.truth = 1;
}
-static const njs_object_prop_t njs_object_null_properties[] =
-{
- { njs_value(NJS_NULL, 0, 0.0),
- njs_string("__proto__"),
- NJS_WHITEOUT, 0, 0, 0, },
-};
-
-
-static nxt_int_t
-njs_object_null_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_object_null_properties,
- nxt_nitems(njs_object_null_properties));
-}
-
-
/*
* The __proto__ property of booleans, numbers and strings primitives
* and Boolean.prototype, Number.prototype, and String.prototype objects.
njs_ret_t
njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
{
- vm->retval.type = NJS_OBJECT;
- vm->retval.data.truth = 1;
+ nxt_uint_t index;
/*
- * The __proto__ getters reside in object prototypes of primitive
- * types. "AND 0x7" maps type of value to prototype offset:
- * NJS_BOOLEAN > NJS_PROTOTYPE_BOOLEAN,
- * NJS_NUMBER > NJS_PROTOTYPE_NUMBER,
- * NJS_STRING > NJS_PROTOTYPE_STRING,
- * NJS_OBJECT > NJS_PROTOTYPE_OBJECT.
- * So "".__proto__ points to String.prototype while
- * String.prototype.__proto__ points to Object.prototype.
+ * The __proto__ getters reside in object prototypes of primitive types
+ * and have to return different results for primitive type and for object
+ * prototype.
*/
- vm->retval.data.u.object = &vm->prototypes[value->type & 7];
+ index = njs_is_object(value) ? NJS_PROTOTYPE_OBJECT:
+ njs_primitive_prototype_index(value->type);
+
+ vm->retval.data.u.object = &vm->prototypes[index];
+ vm->retval.type = NJS_OBJECT;
+ vm->retval.data.truth = 1;
return NXT_OK;
}
*/
njs_ret_t
-njs_object_prototype_create_prototype(njs_vm_t *vm, njs_value_t *value)
+njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value)
{
- int32_t index;
- nxt_int_t ret;
- njs_object_t *prototype;
- njs_function_t *function;
- njs_object_prop_t *prop;
- nxt_lvlhsh_query_t lhq;
+ int32_t index;
+ nxt_int_t ret;
+ njs_function_t *function;
+ njs_object_prop_t *prop;
+ nxt_lvlhsh_query_t lhq;
+
+ static const njs_value_t prototype = njs_string("prototype");
function = value->data.u.function;
index = function - vm->functions;
return NXT_OK;
}
- prop = njs_object_prop_alloc(vm, &njs_string_prototype);
+ prop = njs_object_prop_alloc(vm, &prototype);
if (nxt_slow_path(prop == NULL)) {
return NXT_ERROR;
}
- prototype = &vm->prototypes[index];
-
- prop->value.data.u.object = prototype;
+ prop->value.data.u.object = &vm->prototypes[index];
prop->value.type = NJS_OBJECT;
prop->value.data.truth = 1;
}
-static const njs_object_prop_t njs_object_function_properties[] =
+static const njs_object_prop_t njs_object_constructor_properties[] =
{
/* Object.name == "name". */
{ njs_string("Object"),
NJS_PROPERTY, 0, 0, 0, },
/* Object.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_object_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_object_function_properties,
- nxt_nitems(njs_object_function_properties));
-}
+const njs_object_init_t njs_object_constructor_init = {
+ njs_object_constructor_properties,
+ nxt_nitems(njs_object_constructor_properties),
+};
static njs_ret_t
static njs_ret_t
njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value)
{
- int32_t index;
- nxt_int_t ret;
- njs_value_t *constructor;
- njs_object_t *prototype;
- njs_object_prop_t *prop;
- nxt_lvlhsh_query_t lhq;
+ int32_t index;
+ nxt_int_t ret;
+ njs_value_t *constructor;
+ njs_object_t *prototype;
+ njs_object_prop_t *prop;
+ nxt_lvlhsh_query_t lhq;
+
+ static const njs_value_t constructor_string = njs_string("constructor");
if (njs_is_object(value)) {
prototype = value->data.u.object;
return NXT_ERROR;
} else {
- index = NJS_PROTOTYPE_BOOLEAN + (value->type - NJS_BOOLEAN);
+ index = njs_primitive_prototype_index(value->type);
prototype = &vm->prototypes[index];
}
found:
- prop = njs_object_prop_alloc(vm, &njs_string_constructor);
+ prop = njs_object_prop_alloc(vm, &constructor_string);
if (nxt_slow_path(prop == NULL)) {
return NXT_ERROR;
}
}
+static const njs_value_t njs_object_null_string = njs_string("[object Null]");
+static const njs_value_t njs_object_undefined_string =
+ njs_long_string("[object Undefined]");
+static const njs_value_t njs_object_boolean_string =
+ njs_long_string("[object Boolean]");
+static const njs_value_t njs_object_number_string =
+ njs_long_string("[object Number]");
+static const njs_value_t njs_object_string_string =
+ njs_long_string("[object String]");
+static const njs_value_t njs_object_object_string =
+ njs_long_string("[object Object]");
+static const njs_value_t njs_object_array_string =
+ njs_string("[object Array]");
+static const njs_value_t njs_object_function_string =
+ njs_long_string("[object Function]");
+static const njs_value_t njs_object_regexp_string =
+ njs_long_string("[object RegExp]");
+
+
static njs_ret_t
njs_object_prototype_to_string(njs_vm_t *vm, njs_param_t *param)
{
static const njs_value_t *class_name[] = {
/* Primitives. */
- &njs_string_object_null,
- &njs_string_object_undefined,
- &njs_string_object_boolean,
- &njs_string_object_number,
- &njs_string_object_string,
-
- &njs_string_object_function,
- &njs_string_object_function,
+ &njs_object_null_string,
+ &njs_object_undefined_string,
+ &njs_object_boolean_string,
+ &njs_object_number_string,
+ &njs_object_string_string,
+
+ &njs_object_function_string,
+ &njs_object_function_string,
&njs_string_empty,
/* Objects. */
- &njs_string_object_object,
- &njs_string_object_array,
- &njs_string_object_boolean,
- &njs_string_object_number,
- &njs_string_object_string,
- &njs_string_object_function,
- &njs_string_object_regexp,
+ &njs_object_object_string,
+ &njs_object_array_string,
+ &njs_object_boolean_string,
+ &njs_object_number_string,
+ &njs_object_string_string,
+ &njs_object_function_string,
+ &njs_object_regexp_string,
};
value = param->object;
};
-nxt_int_t
-njs_object_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_object_prototype_properties,
- nxt_nitems(njs_object_prototype_properties));
-}
+const njs_object_init_t njs_object_prototype_init = {
+ njs_object_prototype_properties,
+ nxt_nitems(njs_object_prototype_properties),
+};
#define _NJS_OBJECT_H_INCLUDED_
-struct njs_object_s {
- /* A private hash of njs_object_prop_t. */
- nxt_lvlhsh_t hash;
-
- /* A shared hash of njs_object_prop_t. */
- nxt_lvlhsh_t shared_hash;
-
- /* An object __proto__. */
- njs_object_t *__proto__;
-};
-
-
struct njs_object_value_s {
njs_object_t object;
njs_value_t value;
} njs_object_prop_t;
+struct njs_object_init_s {
+ const njs_object_prop_t *properties;
+ nxt_uint_t items;
+};
+
+
njs_object_t *njs_object_alloc(njs_vm_t *vm);
njs_object_t *njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
- nxt_uint_t prototype);
+ nxt_uint_t type);
njs_ret_t njs_object_method(njs_vm_t *vm, njs_param_t *param,
nxt_lvlhsh_query_t *lhq);
njs_object_prop_t *njs_object_property(njs_vm_t *vm, njs_object_t *obj,
nxt_lvlhsh_query_t *lhq);
nxt_int_t njs_object_hash_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
const njs_object_prop_t *prop, nxt_uint_t n);
-njs_ret_t njs_object_function(njs_vm_t *vm, njs_param_t *param);
+njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_param_t *param);
njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name);
njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
-njs_ret_t njs_object_prototype_create_prototype(njs_vm_t *vm,
- njs_value_t *value);
-nxt_int_t njs_object_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_object_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value);
+
+extern const njs_object_init_t njs_object_constructor_init;
+extern const njs_object_init_t njs_object_prototype_init;
#endif /* _NJS_OBJECT_H_INCLUDED_ */
value->data.u.function->code.script->u.parser = fn_parser;
fn_parser->lexer = parser->lexer;
- fn_parser->values_hash = vm->shared->values_hash;
/* njs_vmcode_return() size. */
fn_parser->code_size = sizeof(njs_vmcode_stop_t);
func->u.parser = fn_parser;
fn_parser->lexer = parser->lexer;
- fn_parser->values_hash = vm->shared->values_hash;
/* njs_vmcode_return() size. */
fn_parser->code_size = sizeof(njs_vmcode_stop_t);
node->index = NJS_INDEX_THIS;
break;
- case NJS_TOKEN_OBJECT_FUNCTION:
+ case NJS_TOKEN_OBJECT_CONSTRUCTOR:
node->index = NJS_INDEX_OBJECT;
break;
- case NJS_TOKEN_ARRAY_FUNCTION:
+ case NJS_TOKEN_ARRAY_CONSTRUCTOR:
node->index = NJS_INDEX_ARRAY;
break;
- case NJS_TOKEN_BOOLEAN_FUNCTION:
+ case NJS_TOKEN_BOOLEAN_CONSTRUCTOR:
node->index = NJS_INDEX_BOOLEAN;
break;
- case NJS_TOKEN_NUMBER_FUNCTION:
+ case NJS_TOKEN_NUMBER_CONSTRUCTOR:
node->index = NJS_INDEX_NUMBER;
break;
- case NJS_TOKEN_STRING_FUNCTION:
+ case NJS_TOKEN_STRING_CONSTRUCTOR:
node->index = NJS_INDEX_STRING;
break;
- case NJS_TOKEN_FUNCTION_FUNCTION:
+ case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
node->index = NJS_INDEX_FUNCTION;
break;
- case NJS_TOKEN_REGEXP_FUNCTION:
+ case NJS_TOKEN_REGEXP_CONSTRUCTOR:
node->index = NJS_INDEX_REGEXP;
break;
NJS_TOKEN_THIS,
- NJS_TOKEN_OBJECT_FUNCTION,
- NJS_TOKEN_ARRAY_FUNCTION,
- NJS_TOKEN_FUNCTION_FUNCTION,
- NJS_TOKEN_REGEXP_FUNCTION,
- NJS_TOKEN_BOOLEAN_FUNCTION,
- NJS_TOKEN_NUMBER_FUNCTION,
- NJS_TOKEN_STRING_FUNCTION,
+ NJS_TOKEN_OBJECT_CONSTRUCTOR,
+ NJS_TOKEN_ARRAY_CONSTRUCTOR,
+ NJS_TOKEN_FUNCTION_CONSTRUCTOR,
+ NJS_TOKEN_REGEXP_CONSTRUCTOR,
+ NJS_TOKEN_BOOLEAN_CONSTRUCTOR,
+ NJS_TOKEN_NUMBER_CONSTRUCTOR,
+ NJS_TOKEN_STRING_CONSTRUCTOR,
NJS_TOKEN_EVAL,
NJS_TOKEN_RESERVED,
nxt_array_t *arguments;
nxt_lvlhsh_t variables_hash;
- nxt_lvlhsh_t values_hash;
- nxt_lvlhsh_t functions_hash;
nxt_array_t *index_cache;
njs_index_t index[NJS_SCOPES - NJS_INDEX_CACHE];
uint8_t scope; /* 4 bits */
uint8_t branch; /* 1 bit */
+ /* Parsing Function() or eval(). */
+ uint8_t runtime; /* 1 bit */
+
size_t code_size;
/* Generator. */
+ sizeof(njs_vmcode_call_t);
break;
- case NJS_TOKEN_OBJECT_FUNCTION:
- case NJS_TOKEN_ARRAY_FUNCTION:
- case NJS_TOKEN_BOOLEAN_FUNCTION:
- case NJS_TOKEN_NUMBER_FUNCTION:
- case NJS_TOKEN_STRING_FUNCTION:
- case NJS_TOKEN_FUNCTION_FUNCTION:
- case NJS_TOKEN_REGEXP_FUNCTION:
+ case NJS_TOKEN_OBJECT_CONSTRUCTOR:
+ case NJS_TOKEN_ARRAY_CONSTRUCTOR:
+ case NJS_TOKEN_BOOLEAN_CONSTRUCTOR:
+ case NJS_TOKEN_NUMBER_CONSTRUCTOR:
+ case NJS_TOKEN_STRING_CONSTRUCTOR:
+ case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
+ case NJS_TOKEN_REGEXP_CONSTRUCTOR:
case NJS_TOKEN_EVAL:
func = njs_parser_node_alloc(vm);
if (nxt_slow_path(func == NULL)) {
njs_ret_t
-njs_regexp_function(njs_vm_t *vm, njs_param_t *param)
+njs_regexp_constructor(njs_vm_t *vm, njs_param_t *param)
{
size_t length;
njs_regexp_t *regexp;
{
njs_regexp_t *regexp;
- regexp = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
- sizeof(njs_regexp_t));
+ regexp = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_regexp_t));
if (nxt_fast_path(regexp != NULL)) {
nxt_lvlhsh_init(®exp->object.hash);
}
-static const njs_object_prop_t njs_regexp_function_properties[] =
+static const njs_object_prop_t njs_regexp_constructor_properties[] =
{
/* RegExp.name == "RegExp". */
{ njs_string("RegExp"),
NJS_PROPERTY, 0, 0, 0, },
/* RegExp.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_regexp_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_regexp_function_properties,
- nxt_nitems(njs_regexp_function_properties));
-}
+const njs_object_init_t njs_regexp_constructor_init = {
+ njs_regexp_constructor_properties,
+ nxt_nitems(njs_regexp_constructor_properties),
+};
static const njs_object_prop_t njs_regexp_prototype_properties[] =
};
-nxt_int_t
-njs_regexp_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_regexp_prototype_properties,
- nxt_nitems(njs_regexp_prototype_properties));
-}
+const njs_object_init_t njs_regexp_prototype_init = {
+ njs_regexp_prototype_properties,
+ nxt_nitems(njs_regexp_prototype_properties),
+};
void
};
-njs_ret_t njs_regexp_function(njs_vm_t *vm, njs_param_t *param);
+njs_ret_t njs_regexp_constructor(njs_vm_t *vm, njs_param_t *param);
nxt_int_t njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser,
njs_value_t *value);
njs_regexp_pattern_t *njs_regexp_pattern_create(njs_vm_t *vm,
u_char *string, size_t length, njs_regexp_flags_t flags);
njs_regexp_t *njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern);
njs_ret_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_regexp_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_regexp_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
void njs_regexp_pattern_free(njs_regexp_pattern_t *pattern);
+extern const njs_object_init_t njs_regexp_constructor_init;
+extern const njs_object_init_t njs_regexp_prototype_init;
+
#endif /* _NJS_REGEXP_H_INCLUDED_ */
+++ /dev/null
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#include <nxt_types.h>
-#include <nxt_clang.h>
-#include <nxt_stub.h>
-#include <nxt_array.h>
-#include <nxt_lvlhsh.h>
-#include <nxt_mem_cache_pool.h>
-#include <njscript.h>
-#include <njs_vm.h>
-#include <njs_boolean.h>
-#include <njs_number.h>
-#include <njs_string.h>
-#include <njs_object.h>
-#include <njs_array.h>
-#include <njs_function.h>
-#include <njs_regexp.h>
-#include <string.h>
-
-
-typedef nxt_int_t (*njs_shared_hash_t) (njs_vm_t *vm, nxt_lvlhsh_t *hash);
-
-
-nxt_int_t
-njs_shared_objects_create(njs_vm_t *vm)
-{
- size_t size;
- nxt_int_t ret;
- nxt_uint_t i;
- njs_object_t *prototypes;
- njs_function_t *functions;
-
- static const njs_shared_hash_t prototype_hash[] = {
- njs_object_prototype_hash,
- njs_array_prototype_hash,
- njs_boolean_prototype_hash,
- njs_number_prototype_hash,
- njs_string_prototype_hash,
- njs_function_prototype_hash,
- njs_regexp_prototype_hash,
- };
-
- static const njs_shared_hash_t function_hash[] = {
- njs_object_function_hash,
- njs_array_function_hash,
- njs_boolean_function_hash,
- njs_number_function_hash,
- njs_string_function_hash,
- njs_function_function_hash,
- njs_regexp_function_hash,
-
- njs_eval_function_hash,
- };
-
- static const njs_native_t native_functions[] = {
- njs_object_function,
- njs_array_function,
- njs_boolean_function,
- njs_number_function,
- njs_string_ctor_function,
- njs_function_function,
- njs_regexp_function,
-
- njs_eval_function,
- };
-
- size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t);
-
- prototypes = nxt_mem_cache_zalign(vm->mem_cache_pool, sizeof(njs_value_t),
- size);
- if (nxt_slow_path(prototypes == NULL)) {
- return NXT_ERROR;
- }
-
- vm->shared->prototypes = prototypes;
-
- for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
- /* TODO: shared hash: prototype & constructor getters, methods */
-
- ret = prototype_hash[i](vm, &prototypes[i].shared_hash);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
- }
-
- size = NJS_FUNCTION_MAX * sizeof(njs_function_t);
-
- functions = nxt_mem_cache_zalign(vm->mem_cache_pool, sizeof(njs_value_t),
- size);
- if (nxt_slow_path(functions == NULL)) {
- return NXT_ERROR;
- }
-
- vm->shared->functions = functions;
-
- for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
- functions[i].native = 1;
- functions[i].args_offset = 1;
- functions[i].code.native = native_functions[i];
-
- ret = function_hash[i](vm, &functions[i].object.shared_hash);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
- }
-
- /* TODO: create function shared hash: prototype+contructor getter */
-
- return NXT_OK;
-}
-
-
-/*
- * Object(),
- * Object.__proto__ -> Function_Prototype,
- * Object_Prototype.__proto__ -> null,
- * the null value is handled by njs_object_prototype_get_proto(),
- *
- * Array(),
- * Array.__proto__ -> Function_Prototype,
- * Array_Prototype.__proto__ -> Object_Prototype,
- *
- * Boolean(),
- * Boolean.__proto__ -> Function_Prototype,
- * Boolean_Prototype.__proto__ -> Object_Prototype,
- *
- * Number(),
- * Number.__proto__ -> Function_Prototype,
- * Number_Prototype.__proto__ -> Object_Prototype,
- *
- * String(),
- * String.__proto__ -> Function_Prototype,
- * String_Prototype.__proto__ -> Object_Prototype,
- *
- * Function(),
- * Function.__proto__ -> Function_Prototype,
- * Function_Prototype.__proto__ -> Object_Prototype,
- *
- * RegExp(),
- * RegExp.__proto__ -> Function_Prototype,
- * RegExp_Prototype.__proto__ -> Object_Prototype,
- *
- * eval(),
- * eval.__proto__ -> Function_Prototype.
- */
-
-nxt_int_t
-njs_shared_objects_clone(njs_vm_t *vm)
-{
- size_t size;
- nxt_uint_t i;
- njs_value_t *values;
- njs_object_t *prototypes;
- njs_function_t *functions;
-
- size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t);
-
- prototypes = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
- size);
- if (nxt_slow_path(prototypes == NULL)) {
- return NXT_ERROR;
- }
-
- vm->prototypes = prototypes;
-
- memcpy(prototypes, vm->shared->prototypes, size);
-
- for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
- prototypes[i].__proto__ = &prototypes[NJS_PROTOTYPE_OBJECT];
- }
-
- size = NJS_FUNCTION_MAX * sizeof(njs_function_t);
-
- functions = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
- size);
- if (nxt_slow_path(functions == NULL)) {
- return NXT_ERROR;
- }
-
- vm->functions = functions;
-
- memcpy(functions, vm->shared->functions, size);
-
- values = vm->scopes[NJS_SCOPE_GLOBAL];
-
- for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
- values[i].type = NJS_FUNCTION;
- values[i].data.truth = 1;
- values[i].data.u.function = &functions[i];
- functions[i].object.__proto__ = &prototypes[NJS_FUNCTION_FUNCTION];
- }
-
- return NXT_OK;
-}
njs_ret_t
-njs_string_ctor_function(njs_vm_t *vm, njs_param_t *param)
+njs_string_constructor(njs_vm_t *vm, njs_param_t *param)
{
njs_object_t *object;
const njs_value_t *value;
}
if (vm->frame->ctor) {
- /* value->type is the same as prototype offset. */
object = njs_object_value_alloc(vm, value, value->type);
if (nxt_slow_path(object == NULL)) {
return NXT_ERROR;
}
-static const njs_object_prop_t njs_string_function_properties[] =
+static const njs_object_prop_t njs_string_constructor_properties[] =
{
/* String.name == "String". */
{ njs_string("String"),
NJS_PROPERTY, 0, 0, 0, },
/* String.prototype. */
- { njs_getter(njs_object_prototype_create_prototype),
+ { njs_getter(njs_object_prototype_create),
njs_string("prototype"),
NJS_NATIVE_GETTER, 0, 0, 0, },
};
-nxt_int_t
-njs_string_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_string_function_properties,
- nxt_nitems(njs_string_function_properties));
-}
+const njs_object_init_t njs_string_constructor_init = {
+ njs_string_constructor_properties,
+ nxt_nitems(njs_string_constructor_properties),
+};
static njs_ret_t
};
-nxt_int_t
-njs_string_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
- return njs_object_hash_create(vm, hash, njs_string_prototype_properties,
- nxt_nitems(njs_string_prototype_properties));
-}
+const njs_object_init_t njs_string_prototype_init = {
+ njs_string_prototype_properties,
+ nxt_nitems(njs_string_prototype_properties),
+};
static nxt_int_t
/*
- * Constant values such as njs_value_zero are copied to vm->values_hash during
+ * Constant values such as njs_value_true are copied to values_hash during
* code generation when them are used as operands to guarantee aligned value.
*/
nxt_int_t ret;
njs_value_t *value;
njs_string_t *string;
+ nxt_lvlhsh_t *values_hash;
nxt_lvlhsh_query_t lhq;
if (src->type != NJS_STRING || src->short_string.size != NJS_STRING_LONG) {
lhq.key.data = start;
lhq.proto = &njs_values_hash_proto;
- if (nxt_lvlhsh_find(&vm->values_hash, &lhq) == NXT_OK) {
+ if (nxt_lvlhsh_find(&vm->shared->values_hash, &lhq) == NXT_OK) {
value = lhq.value;
- } else if (nxt_lvlhsh_find(&parser->values_hash, &lhq) == NXT_OK) {
+ } else if (parser->runtime
+ && nxt_lvlhsh_find(&vm->values_hash, &lhq) == NXT_OK)
+ {
value = lhq.value;
} else {
lhq.value = value;
lhq.pool = vm->mem_cache_pool;
- ret = nxt_lvlhsh_insert(&parser->values_hash, &lhq);
+ values_hash = parser->runtime ? &vm->values_hash:
+ &vm->shared->values_hash;
+
+ ret = nxt_lvlhsh_insert(values_hash, &lhq);
if (nxt_slow_path(ret != NXT_OK)) {
return NJS_INDEX_NONE;
njs_value_t *value);
nxt_noinline size_t njs_string_prop(njs_string_prop_t *string,
njs_value_t *value);
-njs_ret_t njs_string_ctor_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_string_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_string_constructor(njs_vm_t *vm, njs_param_t *param);
void njs_string_offset_map_init(const u_char *start, size_t size);
nxt_bool_t njs_string_eq(const njs_value_t *val1, const njs_value_t *val2);
nxt_int_t njs_string_cmp(const njs_value_t *val1, const njs_value_t *val2);
njs_ret_t njs_value_to_ext_string(njs_vm_t *vm, nxt_str_t *dst,
const njs_value_t *src);
double njs_string_to_number(njs_value_t *value);
-nxt_int_t njs_string_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
njs_index_t njs_value_index(njs_vm_t *vm, njs_parser_t *parser,
const njs_value_t *src);
+extern const njs_object_init_t njs_string_constructor_init;
+extern const njs_object_init_t njs_string_prototype_init;
+
#endif /* _NJS_STRING_H_INCLUDED_ */
const njs_value_t njs_string_empty = njs_string("");
const njs_value_t njs_string_comma = njs_string(",");
-const njs_value_t njs_string_void = njs_string("undefined");
const njs_value_t njs_string_null = njs_string("null");
+const njs_value_t njs_string_void = njs_string("undefined");
const njs_value_t njs_string_boolean = njs_string("boolean");
const njs_value_t njs_string_false = njs_string("false");
const njs_value_t njs_string_true = njs_string("true");
const njs_value_t njs_string_object = njs_string("object");
const njs_value_t njs_string_function = njs_string("function");
const njs_value_t njs_string_native = njs_string("[native code]");
-const njs_value_t njs_string_prototype = njs_string("prototype");
-const njs_value_t njs_string_constructor = njs_string("constructor");
-
-const njs_value_t njs_string_object_null = njs_string("[object Null]");
-const njs_value_t njs_string_object_undefined =
- njs_long_string("[object Undefined]");
-const njs_value_t njs_string_object_boolean =
- njs_long_string("[object Boolean]");
-const njs_value_t njs_string_object_number =
- njs_long_string("[object Number]");
-const njs_value_t njs_string_object_string =
- njs_long_string("[object String]");
-const njs_value_t njs_string_object_object =
- njs_long_string("[object Object]");
-const njs_value_t njs_string_object_array = njs_string("[object Array]");
-const njs_value_t njs_string_object_function =
- njs_long_string("[object Function]");
-const njs_value_t njs_string_object_regexp =
- njs_long_string("[object RegExp]");
const njs_value_t njs_exception_syntax_error = njs_string("SyntaxError");
const njs_value_t njs_exception_reference_error = njs_string("ReferenceError");
return NJS_PRIMITIVE_VALUE;
}
- obj = &vm->prototypes[object->type];
+ obj = &vm->prototypes[njs_primitive_prototype_index(object->type)];
break;
case NJS_STRING:
/*
* The object types have the third bit set. It is used in njs_is_object().
* NJS_OBJECT_BOOLEAN, NJS_OBJECT_NUMBER, and NJS_OBJECT_STRING must be
- * equal to NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING respectively with
- * the third bit set. It is used in njs_primitive_prototype_get_proto()
- * and in njs_property_query(). The order of object types is used in
- * vm->prototypes and vm->functions arrays.
+ * in the same order as NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING. It is
+ * used in njs_primitive_prototype_index(). The order of object types
+ * is used in vm->prototypes and vm->functions arrays.
*/
NJS_OBJECT = 0x08,
NJS_ARRAY = 0x09,
typedef struct njs_string_s njs_string_t;
-typedef struct njs_object_s njs_object_t;
-typedef struct njs_array_s njs_array_t;
+typedef struct njs_object_init_s njs_object_init_t;
typedef struct njs_object_value_s njs_object_value_t;
-typedef struct njs_function_s njs_function_t;
+typedef struct njs_array_s njs_array_t;
typedef struct njs_function_script_s njs_function_script_t;
typedef struct njs_regexp_s njs_regexp_t;
typedef struct njs_regexp_pattern_s njs_regexp_pattern_t;
typedef struct njs_native_frame_s njs_native_frame_t;
+typedef struct njs_object_s njs_object_t;
+
+struct njs_object_s {
+ /* A private hash of njs_object_prop_t. */
+ nxt_lvlhsh_t hash;
+
+ /* A shared hash of njs_object_prop_t. */
+ nxt_lvlhsh_t shared_hash;
+
+ /* An object __proto__. */
+ njs_object_t *__proto__;
+};
+
+
+typedef struct {
+ njs_object_t object;
+
+#if (NXT_64BIT)
+ uint32_t native;
+ uint32_t args_offset;
+#else
+ uint8_t native;
+ uint16_t args_offset;
+#endif
+
+ union {
+ njs_function_script_t *script;
+ njs_native_t native;
+ } code;
+
+ njs_value_t *args;
+} njs_function_t;
+
+
union njs_value_s {
/*
* The njs_value_t size is 16 bytes and must be aligned to 16 bytes
enum njs_prototypes_e {
- NJS_PROTOTYPE_OBJECT = 0,
+ NJS_PROTOTYPE_OBJECT = 0,
NJS_PROTOTYPE_ARRAY,
NJS_PROTOTYPE_BOOLEAN,
NJS_PROTOTYPE_NUMBER,
NJS_PROTOTYPE_STRING,
NJS_PROTOTYPE_FUNCTION,
NJS_PROTOTYPE_REGEXP,
-#define NJS_PROTOTYPE_MAX (NJS_PROTOTYPE_REGEXP + 1)
+#define NJS_PROTOTYPE_MAX (NJS_PROTOTYPE_REGEXP + 1)
};
+#define njs_primitive_prototype_index(type) \
+ (NJS_PROTOTYPE_BOOLEAN + ((type) - NJS_BOOLEAN))
+
+
enum njs_functions_e {
- NJS_FUNCTION_OBJECT = NJS_PROTOTYPE_OBJECT,
- NJS_FUNCTION_ARRAY = NJS_PROTOTYPE_ARRAY,
- NJS_FUNCTION_BOOLEAN = NJS_PROTOTYPE_BOOLEAN,
- NJS_FUNCTION_NUMBER = NJS_PROTOTYPE_NUMBER,
- NJS_FUNCTION_STRING = NJS_PROTOTYPE_STRING,
- NJS_FUNCTION_FUNCTION = NJS_PROTOTYPE_FUNCTION,
- NJS_FUNCTION_REGEXP = NJS_PROTOTYPE_REGEXP,
+ NJS_FUNCTION_OBJECT = NJS_PROTOTYPE_OBJECT,
+ NJS_FUNCTION_ARRAY = NJS_PROTOTYPE_ARRAY,
+ NJS_FUNCTION_BOOLEAN = NJS_PROTOTYPE_BOOLEAN,
+ NJS_FUNCTION_NUMBER = NJS_PROTOTYPE_NUMBER,
+ NJS_FUNCTION_STRING = NJS_PROTOTYPE_STRING,
+ NJS_FUNCTION_FUNCTION = NJS_PROTOTYPE_FUNCTION,
+ NJS_FUNCTION_REGEXP = NJS_PROTOTYPE_REGEXP,
NJS_FUNCTION_EVAL,
-#define NJS_FUNCTION_MAX (NJS_FUNCTION_EVAL + 1)
+#define NJS_FUNCTION_MAX (NJS_FUNCTION_EVAL + 1)
};
nxt_lvlhsh_t externals_hash;
nxt_lvlhsh_t variables_hash;
- nxt_lvlhsh_t functions_hash;
nxt_lvlhsh_t values_hash;
- njs_object_t *prototypes;
- njs_function_t *functions;
+ njs_object_t prototypes[NJS_PROTOTYPE_MAX];
+ njs_function_t functions[NJS_FUNCTION_MAX];
nxt_mem_cache_pool_t *mem_cache_pool;
struct njs_vm_shared_s {
nxt_lvlhsh_t keywords_hash;
nxt_lvlhsh_t values_hash;
+ nxt_lvlhsh_t null_proto_hash;
- njs_object_t *prototypes;
- njs_function_t *functions;
+ njs_object_t prototypes[NJS_PROTOTYPE_MAX];
+ njs_function_t functions[NJS_FUNCTION_MAX];
};
nxt_noinline void njs_number_set(njs_value_t *value, double num);
-nxt_int_t njs_shared_objects_create(njs_vm_t *vm);
-nxt_int_t njs_shared_objects_clone(njs_vm_t *vm);
+nxt_int_t njs_builtin_objects_create(njs_vm_t *vm);
+nxt_int_t njs_builtin_objects_clone(njs_vm_t *vm);
void *njs_lvlhsh_alloc(void *data, size_t size, nxt_uint_t nalloc);
extern const njs_value_t njs_string_minus_infinity;
extern const njs_value_t njs_string_plus_infinity;
extern const njs_value_t njs_string_nan;
-extern const njs_value_t njs_string_prototype;
-extern const njs_value_t njs_string_constructor;
-
-extern const njs_value_t njs_string_object_null;
-extern const njs_value_t njs_string_object_undefined;
-extern const njs_value_t njs_string_object_boolean;
-extern const njs_value_t njs_string_object_number;
-extern const njs_value_t njs_string_object_string;
-extern const njs_value_t njs_string_object_object;
-extern const njs_value_t njs_string_object_array;
-extern const njs_value_t njs_string_object_function;
-extern const njs_value_t njs_string_object_regexp;
extern const njs_value_t njs_exception_syntax_error;
extern const njs_value_t njs_exception_reference_error;
njs_vm_create(nxt_mem_cache_pool_t *mcp, njs_vm_shared_t **shared,
nxt_lvlhsh_t *externals)
{
- njs_vm_t *vm;
+ njs_vm_t *vm;
+ nxt_int_t ret;
if (mcp == NULL) {
mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
- NULL, 2 * nxt_pagesize(), 128, 512, 16);
+ NULL, 2 * nxt_pagesize(), 128, 512, 16);
if (nxt_slow_path(mcp == NULL)) {
return NULL;
}
if (nxt_fast_path(vm != NULL)) {
vm->mem_cache_pool = mcp;
- if (shared != NULL) {
+ if (shared != NULL && *shared != NULL) {
+ vm->shared = *shared;
- if (*shared == NULL) {
- *shared = nxt_mem_cache_zalloc(mcp, sizeof(njs_vm_shared_t));
- if (nxt_slow_path(*shared == NULL)) {
- return NULL;
- }
+ } else {
+ vm->shared = nxt_mem_cache_zalloc(mcp, sizeof(njs_vm_shared_t));
+
+ if (nxt_slow_path(vm->shared == NULL)) {
+ return NULL;
}
- vm->shared = *shared;
+ if (shared != NULL) {
+ *shared = vm->shared;
+ }
+
+ nxt_lvlhsh_init(&vm->shared->keywords_hash);
+
+ ret = njs_lexer_keywords_init(mcp, &vm->shared->keywords_hash);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
+
+ nxt_lvlhsh_init(&vm->shared->values_hash);
+
+ ret = njs_builtin_objects_create(vm);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NULL;
+ }
}
+ nxt_lvlhsh_init(&vm->values_hash);
+
if (externals != NULL) {
vm->externals_hash = *externals;
}
nxt_int_t ret;
njs_lexer_t *lexer;
njs_parser_t *parser;
- nxt_lvlhsh_t keywords_hash;
njs_parser_node_t *node;
parser = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_parser_t));
}
parser->lexer = lexer;
-
- if (vm->shared != NULL) {
- keywords_hash = vm->shared->keywords_hash;
- parser->values_hash = vm->shared->values_hash;
-
- /* STUB */
- if (vm->shared->prototypes == NULL) {
- ret = njs_shared_objects_create(vm);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_ERROR;
- }
- }
-
- } else {
- nxt_lvlhsh_init(&keywords_hash);
- }
-
- if (nxt_lvlhsh_is_empty(&keywords_hash)) {
-
- ret = njs_lexer_keywords_init(vm->mem_cache_pool, &keywords_hash);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NJS_ERROR;
- }
-
- if (vm->shared != NULL) {
- vm->shared->keywords_hash = keywords_hash;
- }
- }
-
- parser->lexer->keywords_hash = keywords_hash;
-
- parser->lexer->start = *start;
- parser->lexer->end = end;
+ lexer->start = *start;
+ lexer->end = end;
+ lexer->keywords_hash = vm->shared->keywords_hash;
parser->code_size = sizeof(njs_vmcode_stop_t);
parser->scope = NJS_SCOPE_GLOBAL;
vm->global_scope = parser->local_scope;
vm->scope_size = parser->scope_size;
-
vm->variables_hash = parser->variables_hash;
- vm->values_hash = parser->values_hash;
-
- if (vm->shared != NULL) {
- vm->shared->values_hash = parser->values_hash;
- }
vm->parser = NULL;
memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope,
vm->scope_size);
- ret = njs_shared_objects_clone(nvm);
+ ret = njs_builtin_objects_clone(nvm);
if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}