2012-01-26 21:47:57 +00:00
|
|
|
// Copyright 2012 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
#ifndef V8_CONTEXTS_H_
|
|
|
|
#define V8_CONTEXTS_H_
|
|
|
|
|
2014-08-05 08:18:22 +00:00
|
|
|
#include "src/heap/heap.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/objects.h"
|
2010-08-30 07:10:40 +00:00
|
|
|
|
2009-05-25 10:05:56 +00:00
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
enum ContextLookupFlags {
|
|
|
|
FOLLOW_CONTEXT_CHAIN = 1,
|
|
|
|
FOLLOW_PROTOTYPE_CHAIN = 2,
|
|
|
|
|
|
|
|
DONT_FOLLOW_CHAINS = 0,
|
|
|
|
FOLLOW_CHAINS = FOLLOW_CONTEXT_CHAIN | FOLLOW_PROTOTYPE_CHAIN
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-08-30 11:23:57 +00:00
|
|
|
// ES5 10.2 defines lexical environments with mutable and immutable bindings.
|
|
|
|
// Immutable bindings have two states, initialized and uninitialized, and
|
2011-10-25 08:33:08 +00:00
|
|
|
// their state is changed by the InitializeImmutableBinding method. The
|
|
|
|
// BindingFlags enum represents information if a binding has definitely been
|
|
|
|
// initialized. A mutable binding does not need to be checked and thus has
|
|
|
|
// the BindingFlag MUTABLE_IS_INITIALIZED.
|
|
|
|
//
|
|
|
|
// There are two possibilities for immutable bindings
|
|
|
|
// * 'const' declared variables. They are initialized when evaluating the
|
|
|
|
// corresponding declaration statement. They need to be checked for being
|
|
|
|
// initialized and thus get the flag IMMUTABLE_CHECK_INITIALIZED.
|
|
|
|
// * The function name of a named function literal. The binding is immediately
|
|
|
|
// initialized when entering the function and thus does not need to be
|
|
|
|
// checked. it gets the BindingFlag IMMUTABLE_IS_INITIALIZED.
|
|
|
|
// Accessing an uninitialized binding produces the undefined value.
|
2011-08-30 11:23:57 +00:00
|
|
|
//
|
|
|
|
// The harmony proposal for block scoped bindings also introduces the
|
2011-10-25 08:33:08 +00:00
|
|
|
// uninitialized state for mutable bindings.
|
|
|
|
// * A 'let' declared variable. They are initialized when evaluating the
|
|
|
|
// corresponding declaration statement. They need to be checked for being
|
|
|
|
// initialized and thus get the flag MUTABLE_CHECK_INITIALIZED.
|
|
|
|
// * A 'var' declared variable. It is initialized immediately upon creation
|
|
|
|
// and thus doesn't need to be checked. It gets the flag
|
|
|
|
// MUTABLE_IS_INITIALIZED.
|
|
|
|
// * Catch bound variables, function parameters and variables introduced by
|
|
|
|
// function declarations are initialized immediately and do not need to be
|
|
|
|
// checked. Thus they get the flag MUTABLE_IS_INITIALIZED.
|
|
|
|
// Immutable bindings in harmony mode get the _HARMONY flag variants. Accessing
|
|
|
|
// an uninitialized binding produces a reference error.
|
|
|
|
//
|
|
|
|
// In V8 uninitialized bindings are set to the hole value upon creation and set
|
|
|
|
// to a different value upon initialization.
|
2011-08-30 11:23:57 +00:00
|
|
|
enum BindingFlags {
|
|
|
|
MUTABLE_IS_INITIALIZED,
|
|
|
|
MUTABLE_CHECK_INITIALIZED,
|
|
|
|
IMMUTABLE_IS_INITIALIZED,
|
|
|
|
IMMUTABLE_CHECK_INITIALIZED,
|
2011-10-25 08:33:08 +00:00
|
|
|
IMMUTABLE_IS_INITIALIZED_HARMONY,
|
|
|
|
IMMUTABLE_CHECK_INITIALIZED_HARMONY,
|
2011-08-30 11:23:57 +00:00
|
|
|
MISSING_BINDING
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Heap-allocated activation contexts.
|
|
|
|
//
|
|
|
|
// Contexts are implemented as FixedArray objects; the Context
|
|
|
|
// class is a convenience interface casted on a FixedArray object.
|
|
|
|
//
|
|
|
|
// Note: Context must have no virtual functions and Context objects
|
|
|
|
// must always be allocated via Heap::AllocateContext() or
|
|
|
|
// Factory::NewContext.
|
|
|
|
|
2014-07-07 13:27:37 +00:00
|
|
|
#define NATIVE_CONTEXT_FIELDS(V) \
|
|
|
|
V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \
|
|
|
|
V(SECURITY_TOKEN_INDEX, Object, security_token) \
|
|
|
|
V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
|
|
|
|
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
|
|
|
|
V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
|
|
|
|
V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
|
|
|
|
V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \
|
|
|
|
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
|
|
|
|
V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
|
|
|
|
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
|
|
|
|
V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \
|
|
|
|
V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
|
|
|
|
V(JSON_OBJECT_INDEX, JSObject, json_object) \
|
|
|
|
V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
|
|
|
|
V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
|
|
|
|
V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \
|
|
|
|
V(CREATE_DATE_FUN_INDEX, JSFunction, create_date_fun) \
|
|
|
|
V(TO_NUMBER_FUN_INDEX, JSFunction, to_number_fun) \
|
|
|
|
V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun) \
|
|
|
|
V(TO_DETAIL_STRING_FUN_INDEX, JSFunction, to_detail_string_fun) \
|
|
|
|
V(TO_OBJECT_FUN_INDEX, JSFunction, to_object_fun) \
|
|
|
|
V(TO_INTEGER_FUN_INDEX, JSFunction, to_integer_fun) \
|
|
|
|
V(TO_UINT32_FUN_INDEX, JSFunction, to_uint32_fun) \
|
|
|
|
V(TO_INT32_FUN_INDEX, JSFunction, to_int32_fun) \
|
2014-12-15 19:08:32 +00:00
|
|
|
V(TO_LENGTH_FUN_INDEX, JSFunction, to_length_fun) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \
|
|
|
|
V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \
|
|
|
|
V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \
|
|
|
|
V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \
|
|
|
|
V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \
|
|
|
|
V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \
|
|
|
|
V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \
|
|
|
|
V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \
|
|
|
|
V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun) \
|
|
|
|
V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \
|
|
|
|
V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \
|
|
|
|
V(INT8_ARRAY_EXTERNAL_MAP_INDEX, Map, int8_array_external_map) \
|
|
|
|
V(UINT8_ARRAY_EXTERNAL_MAP_INDEX, Map, uint8_array_external_map) \
|
|
|
|
V(INT16_ARRAY_EXTERNAL_MAP_INDEX, Map, int16_array_external_map) \
|
|
|
|
V(UINT16_ARRAY_EXTERNAL_MAP_INDEX, Map, uint16_array_external_map) \
|
|
|
|
V(INT32_ARRAY_EXTERNAL_MAP_INDEX, Map, int32_array_external_map) \
|
|
|
|
V(UINT32_ARRAY_EXTERNAL_MAP_INDEX, Map, uint32_array_external_map) \
|
|
|
|
V(FLOAT32_ARRAY_EXTERNAL_MAP_INDEX, Map, float32_array_external_map) \
|
|
|
|
V(FLOAT64_ARRAY_EXTERNAL_MAP_INDEX, Map, float64_array_external_map) \
|
|
|
|
V(UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX, Map, \
|
|
|
|
uint8_clamped_array_external_map) \
|
|
|
|
V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \
|
|
|
|
V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \
|
|
|
|
V(SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map, \
|
|
|
|
sloppy_function_with_readonly_prototype_map) \
|
|
|
|
V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map) \
|
2015-02-25 14:52:36 +00:00
|
|
|
V(STRONG_FUNCTION_MAP_INDEX, Map, strong_function_map) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
|
|
|
|
sloppy_function_without_prototype_map) \
|
|
|
|
V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
|
|
|
|
strict_function_without_prototype_map) \
|
2015-02-25 14:52:36 +00:00
|
|
|
V(STRONG_CONSTRUCTOR_MAP_INDEX, Map, strong_constructor_map) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(BOUND_FUNCTION_MAP_INDEX, Map, bound_function_map) \
|
|
|
|
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map) \
|
|
|
|
V(SLOPPY_ARGUMENTS_MAP_INDEX, Map, sloppy_arguments_map) \
|
|
|
|
V(ALIASED_ARGUMENTS_MAP_INDEX, Map, aliased_arguments_map) \
|
|
|
|
V(STRICT_ARGUMENTS_MAP_INDEX, Map, strict_arguments_map) \
|
|
|
|
V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \
|
|
|
|
V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \
|
|
|
|
V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \
|
|
|
|
V(CONFIGURE_GLOBAL_INDEX, JSFunction, configure_global_fun) \
|
2015-03-09 12:26:22 +00:00
|
|
|
V(FUNCTION_CACHE_INDEX, ObjectHashTable, function_cache) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(JSFUNCTION_RESULT_CACHES_INDEX, FixedArray, jsfunction_result_caches) \
|
2014-08-11 14:54:15 +00:00
|
|
|
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(RUNTIME_CONTEXT_INDEX, Context, runtime_context) \
|
|
|
|
V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
|
|
|
|
V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \
|
|
|
|
call_as_constructor_delegate) \
|
|
|
|
V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
|
|
|
|
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
|
|
|
|
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
|
|
|
|
V(MAP_CACHE_INDEX, Object, map_cache) \
|
|
|
|
V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \
|
|
|
|
V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
|
|
|
|
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
|
|
|
|
error_message_for_code_gen_from_strings) \
|
2015-03-11 12:14:08 +00:00
|
|
|
V(PROMISE_STATUS_INDEX, Symbol, promise_status) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
|
|
|
|
V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
|
|
|
|
V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
|
|
|
|
V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain) \
|
|
|
|
V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
|
|
|
|
V(PROMISE_THEN_INDEX, JSFunction, promise_then) \
|
|
|
|
V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
|
|
|
|
to_complete_property_descriptor) \
|
|
|
|
V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
|
|
|
|
V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \
|
|
|
|
V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap) \
|
|
|
|
V(PROXY_ENUMERATE_INDEX, JSFunction, proxy_enumerate) \
|
|
|
|
V(OBSERVERS_NOTIFY_CHANGE_INDEX, JSFunction, observers_notify_change) \
|
|
|
|
V(OBSERVERS_ENQUEUE_SPLICE_INDEX, JSFunction, observers_enqueue_splice) \
|
|
|
|
V(OBSERVERS_BEGIN_SPLICE_INDEX, JSFunction, observers_begin_perform_splice) \
|
|
|
|
V(OBSERVERS_END_SPLICE_INDEX, JSFunction, observers_end_perform_splice) \
|
|
|
|
V(NATIVE_OBJECT_OBSERVE_INDEX, JSFunction, native_object_observe) \
|
|
|
|
V(NATIVE_OBJECT_GET_NOTIFIER_INDEX, JSFunction, native_object_get_notifier) \
|
|
|
|
V(NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE, JSFunction, \
|
|
|
|
native_object_notifier_perform_change) \
|
|
|
|
V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map) \
|
|
|
|
V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \
|
2015-02-25 14:52:36 +00:00
|
|
|
V(STRONG_GENERATOR_FUNCTION_MAP_INDEX, Map, strong_generator_function_map) \
|
2014-07-07 13:27:37 +00:00
|
|
|
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, generator_object_prototype_map) \
|
|
|
|
V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
|
|
|
|
V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \
|
|
|
|
V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map) \
|
2014-11-07 16:29:13 +00:00
|
|
|
V(ARRAY_VALUES_ITERATOR_INDEX, JSFunction, array_values_iterator) \
|
2014-11-12 11:34:09 +00:00
|
|
|
V(SCRIPT_CONTEXT_TABLE_INDEX, ScriptContextTable, script_context_table)
|
2014-11-07 16:29:13 +00:00
|
|
|
|
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
// A table of all script contexts. Every loaded top-level script with top-level
|
|
|
|
// lexical declarations contributes its ScriptContext into this table.
|
2014-11-07 16:29:13 +00:00
|
|
|
//
|
|
|
|
// The table is a fixed array, its first slot is the current used count and
|
2014-11-12 11:34:09 +00:00
|
|
|
// the subsequent slots 1..used contain ScriptContexts.
|
|
|
|
class ScriptContextTable : public FixedArray {
|
2014-11-07 16:29:13 +00:00
|
|
|
public:
|
|
|
|
// Conversions.
|
2014-11-12 11:34:09 +00:00
|
|
|
static ScriptContextTable* cast(Object* context) {
|
|
|
|
DCHECK(context->IsScriptContextTable());
|
|
|
|
return reinterpret_cast<ScriptContextTable*>(context);
|
2014-11-07 16:29:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct LookupResult {
|
|
|
|
int context_index;
|
|
|
|
int slot_index;
|
|
|
|
VariableMode mode;
|
|
|
|
InitializationFlag init_flag;
|
|
|
|
MaybeAssignedFlag maybe_assigned_flag;
|
|
|
|
};
|
|
|
|
|
|
|
|
int used() const { return Smi::cast(get(kUsedSlot))->value(); }
|
|
|
|
|
|
|
|
void set_used(int used) { set(kUsedSlot, Smi::FromInt(used)); }
|
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
static Handle<Context> GetContext(Handle<ScriptContextTable> table, int i) {
|
2014-11-07 16:29:13 +00:00
|
|
|
DCHECK(i < table->used());
|
|
|
|
return Handle<Context>::cast(FixedArray::get(table, i + 1));
|
|
|
|
}
|
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
// Lookup a variable `name` in a ScriptContextTable.
|
2014-11-07 16:29:13 +00:00
|
|
|
// If it returns true, the variable is found and `result` contains
|
|
|
|
// valid information about its location.
|
|
|
|
// If it returns false, `result` is untouched.
|
|
|
|
MUST_USE_RESULT
|
2014-11-12 11:34:09 +00:00
|
|
|
static bool Lookup(Handle<ScriptContextTable> table, Handle<String> name,
|
2014-11-07 16:29:13 +00:00
|
|
|
LookupResult* result);
|
|
|
|
|
|
|
|
MUST_USE_RESULT
|
2014-11-12 11:34:09 +00:00
|
|
|
static Handle<ScriptContextTable> Extend(Handle<ScriptContextTable> table,
|
|
|
|
Handle<Context> script_context);
|
2014-11-07 16:29:13 +00:00
|
|
|
|
2014-11-11 11:16:30 +00:00
|
|
|
static int GetContextOffset(int context_index) {
|
|
|
|
return kFirstContextOffset + context_index * kPointerSize;
|
|
|
|
}
|
|
|
|
|
2014-11-07 16:29:13 +00:00
|
|
|
private:
|
|
|
|
static const int kUsedSlot = 0;
|
2014-11-11 11:16:30 +00:00
|
|
|
static const int kFirstContextOffset =
|
|
|
|
FixedArray::kHeaderSize + (kUsedSlot + 1) * kPointerSize;
|
2014-11-07 16:29:13 +00:00
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptContextTable);
|
2014-11-07 16:29:13 +00:00
|
|
|
};
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// JSFunctions are pairs (context, function code), sometimes also called
|
|
|
|
// closures. A Context object is used to represent function contexts and
|
|
|
|
// dynamically pushed 'with' contexts (or 'scopes' in ECMA-262 speak).
|
|
|
|
//
|
|
|
|
// At runtime, the contexts build a stack in parallel to the execution
|
|
|
|
// stack, with the top-most context being the current context. All contexts
|
|
|
|
// have the following slots:
|
|
|
|
//
|
|
|
|
// [ closure ] This is the current function. It is the same for all
|
|
|
|
// contexts inside a function. It provides access to the
|
|
|
|
// incoming context (i.e., the outer context, which may
|
|
|
|
// or may not become the current function's context), and
|
|
|
|
// it provides access to the functions code and thus it's
|
|
|
|
// scope information, which in turn contains the names of
|
|
|
|
// statically allocated context slots. The names are needed
|
|
|
|
// for dynamic lookups in the presence of 'with' or 'eval'.
|
|
|
|
//
|
|
|
|
// [ previous ] A pointer to the previous context. It is NULL for
|
|
|
|
// function contexts, and non-NULL for 'with' contexts.
|
|
|
|
// Used to implement the 'with' statement.
|
|
|
|
//
|
|
|
|
// [ extension ] A pointer to an extension JSObject, or NULL. Used to
|
|
|
|
// implement 'with' statements and dynamic declarations
|
|
|
|
// (through 'eval'). The object in a 'with' statement is
|
|
|
|
// stored in the extension slot of a 'with' context.
|
|
|
|
// Dynamically declared variables/functions are also added
|
|
|
|
// to lazily allocated extension object. Context::Lookup
|
|
|
|
// searches the extension object for properties.
|
2012-08-27 09:40:26 +00:00
|
|
|
// For global and block contexts, contains the respective
|
|
|
|
// ScopeInfo.
|
2012-07-09 08:59:03 +00:00
|
|
|
// For module contexts, points back to the respective JSModule.
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
2012-08-17 12:59:00 +00:00
|
|
|
// [ global_object ] A pointer to the global object. Provided for quick
|
2008-07-03 15:10:15 +00:00
|
|
|
// access to the global object from inside the code (since
|
|
|
|
// we always have a context pointer).
|
|
|
|
//
|
|
|
|
// In addition, function contexts may have statically allocated context slots
|
|
|
|
// to store local variables/functions that are accessed from inner functions
|
|
|
|
// (via static context addresses) or through 'eval' (dynamic context lookups).
|
2014-02-27 13:25:05 +00:00
|
|
|
// The native context contains additional slots for fast access to native
|
|
|
|
// properties.
|
|
|
|
//
|
|
|
|
// Finally, with Harmony scoping, the JSFunction representing a top level
|
2014-11-12 11:34:09 +00:00
|
|
|
// script will have the ScriptContext rather than a FunctionContext.
|
|
|
|
// Script contexts from all top-level scripts are gathered in
|
|
|
|
// ScriptContextTable.
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
class Context: public FixedArray {
|
|
|
|
public:
|
|
|
|
// Conversions.
|
|
|
|
static Context* cast(Object* context) {
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(context->IsContext());
|
2008-07-03 15:10:15 +00:00
|
|
|
return reinterpret_cast<Context*>(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
// The default context slot layout; indices are FixedArray slot indices.
|
|
|
|
enum {
|
|
|
|
// These slots are in all contexts.
|
|
|
|
CLOSURE_INDEX,
|
|
|
|
PREVIOUS_INDEX,
|
2011-06-16 06:37:49 +00:00
|
|
|
// The extension slot is used for either the global object (in global
|
|
|
|
// contexts), eval extension object (function contexts), subject of with
|
2011-10-21 10:26:59 +00:00
|
|
|
// (with contexts), or the variable name (catch contexts), the serialized
|
2012-07-09 08:59:03 +00:00
|
|
|
// scope info (block contexts), or the module instance (module contexts).
|
2008-07-03 15:10:15 +00:00
|
|
|
EXTENSION_INDEX,
|
2012-08-17 12:59:00 +00:00
|
|
|
GLOBAL_OBJECT_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
MIN_CONTEXT_SLOTS,
|
|
|
|
|
2011-06-16 06:37:49 +00:00
|
|
|
// This slot holds the thrown value in catch contexts.
|
|
|
|
THROWN_OBJECT_INDEX = MIN_CONTEXT_SLOTS,
|
|
|
|
|
2012-08-17 09:03:08 +00:00
|
|
|
// These slots are only in native contexts.
|
Split window support from V8.
Here is a description of the background and design of split window in Chrome and V8:
https://docs.google.com/a/google.com/Doc?id=chhjkpg_47fwddxbfr
This change list splits the window object into two parts: 1) an inner window object used as the global object of contexts; 2) an outer window object exposed to JavaScript and accessible by the name 'window'. Firefox did it awhile ago, here are some discussions: https://wiki.mozilla.org/Gecko:SplitWindow. One additional benefit of splitting window in Chrome is that accessing global variables don't need security checks anymore, it can improve applications that use many global variables.
V8 support of split window:
There are a small number of changes on V8 api to support split window:
Security context is removed from V8, so does related API functions;
A global object can be detached from its context and reused by a new context;
Access checks on an object template can be turned on/off by default;
An object can turn on its access checks later;
V8 has a new object type, ApiGlobalObject, which is the outer window object type. The existing JSGlobalObject becomes the inner window object type. Security checks are moved from JSGlobalObject to ApiGlobalObject. ApiGlobalObject is the one exposed to JavaScript, it is accessible through Context::Global(). ApiGlobalObject's prototype is set to JSGlobalObject so that property lookups are forwarded to JSGlobalObject. ApiGlobalObject forwards all other property access requests to JSGlobalObject, such as SetProperty, DeleteProperty, etc.
Security token is moved to a global context, and ApiGlobalObject has a reference to its global context. JSGlobalObject has a reference to its global context as well. When accessing properties on a global object in JavaScript, the domain security check is performed by comparing the security token of the lexical context (Top::global_context()) to the token of global object's context. The check is only needed when the receiver is a window object, such as 'window.document'. Accessing global variables, such as 'var foo = 3; foo' does not need checks because the receiver is the inner window object.
When an outer window is detached from its global context (when a frame navigates away from a page), it is completely detached from the inner window. A new context is created for the new page, and the outer global object is reused. At this point, the access check on the DOMWindow wrapper of the old context is turned on. The code in old context is still able to access DOMWindow properties, but it has to go through domain security checks.
It is debatable on how to implement the outer window object. Currently each property access function has to check if the receiver is ApiGlobalObject type. This approach might be error-prone that one may forget to check the receiver when adding new functions. It is unlikely a performance issue because accessing global variables are more common than 'window.foo' style coding.
I am still working on the ARM port, and I'd like to hear comments and suggestions on the best way to support it in V8.
Review URL: http://codereview.chromium.org/7366
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@540 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2008-10-21 19:07:58 +00:00
|
|
|
GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
|
|
|
|
SECURITY_TOKEN_INDEX,
|
2014-07-07 13:27:37 +00:00
|
|
|
SLOPPY_ARGUMENTS_MAP_INDEX,
|
|
|
|
ALIASED_ARGUMENTS_MAP_INDEX,
|
|
|
|
STRICT_ARGUMENTS_MAP_INDEX,
|
2010-04-13 09:31:03 +00:00
|
|
|
REGEXP_RESULT_MAP_INDEX,
|
2014-03-11 14:41:22 +00:00
|
|
|
SLOPPY_FUNCTION_MAP_INDEX,
|
2014-05-09 17:59:15 +00:00
|
|
|
SLOPPY_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX,
|
2014-03-11 14:41:22 +00:00
|
|
|
STRICT_FUNCTION_MAP_INDEX,
|
2015-02-25 14:52:36 +00:00
|
|
|
STRONG_FUNCTION_MAP_INDEX,
|
2014-03-11 14:41:22 +00:00
|
|
|
SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
|
|
|
|
STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
|
2015-02-25 14:52:36 +00:00
|
|
|
STRONG_CONSTRUCTOR_MAP_INDEX,
|
2014-06-13 12:19:04 +00:00
|
|
|
BOUND_FUNCTION_MAP_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
INITIAL_OBJECT_PROTOTYPE_INDEX,
|
2013-05-13 07:35:26 +00:00
|
|
|
INITIAL_ARRAY_PROTOTYPE_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
BOOLEAN_FUNCTION_INDEX,
|
|
|
|
NUMBER_FUNCTION_INDEX,
|
|
|
|
STRING_FUNCTION_INDEX,
|
2010-08-12 13:43:08 +00:00
|
|
|
STRING_FUNCTION_PROTOTYPE_MAP_INDEX,
|
2013-03-22 16:33:50 +00:00
|
|
|
SYMBOL_FUNCTION_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
OBJECT_FUNCTION_INDEX,
|
2011-12-27 15:12:12 +00:00
|
|
|
INTERNAL_ARRAY_FUNCTION_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
ARRAY_FUNCTION_INDEX,
|
2012-05-23 14:24:29 +00:00
|
|
|
JS_ARRAY_MAPS_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
DATE_FUNCTION_INDEX,
|
2009-04-24 08:13:09 +00:00
|
|
|
JSON_OBJECT_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
REGEXP_FUNCTION_INDEX,
|
|
|
|
CREATE_DATE_FUN_INDEX,
|
|
|
|
TO_NUMBER_FUN_INDEX,
|
|
|
|
TO_STRING_FUN_INDEX,
|
|
|
|
TO_DETAIL_STRING_FUN_INDEX,
|
|
|
|
TO_OBJECT_FUN_INDEX,
|
|
|
|
TO_INTEGER_FUN_INDEX,
|
|
|
|
TO_UINT32_FUN_INDEX,
|
|
|
|
TO_INT32_FUN_INDEX,
|
|
|
|
TO_BOOLEAN_FUN_INDEX,
|
2010-01-05 09:38:02 +00:00
|
|
|
GLOBAL_EVAL_FUN_INDEX,
|
2013-04-25 12:02:23 +00:00
|
|
|
ARRAY_BUFFER_FUN_INDEX,
|
2013-04-29 11:09:03 +00:00
|
|
|
UINT8_ARRAY_FUN_INDEX,
|
|
|
|
INT8_ARRAY_FUN_INDEX,
|
|
|
|
UINT16_ARRAY_FUN_INDEX,
|
|
|
|
INT16_ARRAY_FUN_INDEX,
|
|
|
|
UINT32_ARRAY_FUN_INDEX,
|
|
|
|
INT32_ARRAY_FUN_INDEX,
|
2014-01-24 16:01:15 +00:00
|
|
|
FLOAT32_ARRAY_FUN_INDEX,
|
|
|
|
FLOAT64_ARRAY_FUN_INDEX,
|
|
|
|
UINT8_CLAMPED_ARRAY_FUN_INDEX,
|
2014-04-22 12:24:28 +00:00
|
|
|
INT8_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
UINT8_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
INT16_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
UINT16_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
INT32_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
UINT32_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
FLOAT32_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
FLOAT64_ARRAY_EXTERNAL_MAP_INDEX,
|
|
|
|
UINT8_CLAMPED_ARRAY_EXTERNAL_MAP_INDEX,
|
2013-06-21 13:02:38 +00:00
|
|
|
DATA_VIEW_FUN_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
MESSAGE_LISTENERS_INDEX,
|
|
|
|
MAKE_MESSAGE_FUN_INDEX,
|
|
|
|
GET_STACK_TRACE_LINE_INDEX,
|
|
|
|
CONFIGURE_GLOBAL_INDEX,
|
|
|
|
FUNCTION_CACHE_INDEX,
|
2010-04-14 14:46:15 +00:00
|
|
|
JSFUNCTION_RESULT_CACHES_INDEX,
|
2010-08-25 13:25:54 +00:00
|
|
|
NORMALIZED_MAP_CACHE_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
RUNTIME_CONTEXT_INDEX,
|
|
|
|
CALL_AS_FUNCTION_DELEGATE_INDEX,
|
2009-05-20 19:33:44 +00:00
|
|
|
CALL_AS_CONSTRUCTOR_DELEGATE_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
SCRIPT_FUNCTION_INDEX,
|
2010-02-24 19:59:09 +00:00
|
|
|
OPAQUE_REFERENCE_FUNCTION_INDEX,
|
2008-07-03 15:10:15 +00:00
|
|
|
CONTEXT_EXTENSION_FUNCTION_INDEX,
|
|
|
|
OUT_OF_MEMORY_INDEX,
|
2012-11-13 12:27:03 +00:00
|
|
|
EMBEDDER_DATA_INDEX,
|
2011-05-03 05:40:47 +00:00
|
|
|
ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
|
2012-09-17 09:58:22 +00:00
|
|
|
ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
|
2013-11-27 17:21:40 +00:00
|
|
|
RUN_MICROTASKS_INDEX,
|
2014-05-02 08:00:47 +00:00
|
|
|
ENQUEUE_MICROTASK_INDEX,
|
2015-03-11 12:14:08 +00:00
|
|
|
PROMISE_STATUS_INDEX,
|
2014-03-11 16:17:20 +00:00
|
|
|
PROMISE_CREATE_INDEX,
|
|
|
|
PROMISE_RESOLVE_INDEX,
|
|
|
|
PROMISE_REJECT_INDEX,
|
|
|
|
PROMISE_CHAIN_INDEX,
|
|
|
|
PROMISE_CATCH_INDEX,
|
2014-06-12 11:33:30 +00:00
|
|
|
PROMISE_THEN_INDEX,
|
2011-09-21 12:45:51 +00:00
|
|
|
TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
|
2011-07-19 09:38:59 +00:00
|
|
|
DERIVED_HAS_TRAP_INDEX,
|
2011-05-18 14:00:34 +00:00
|
|
|
DERIVED_GET_TRAP_INDEX,
|
Implement set trap for proxies, and revamp class hierarchy in preparation:
- Introduce a class JSReceiver, that is a common superclass of JSObject and
JSProxy. Use JSReceiver where appropriate (probably lots of places that we
still have to migrate, but we will find those later with proxy test suite).
- Move appropriate methods to JSReceiver class (SetProperty,
GetPropertyAttribute, Get/SetPrototype, Lookup, and so on).
- Introduce new JSFunctionProxy subclass of JSProxy. Currently only a stub.
- Overhaul enum InstanceType:
* Introduce FIRST/LAST_SPEC_OBJECT_TYPE that ranges over all types that
represent JS objects, and use that consistently to check language types.
* Rename FIRST/LAST_JS_OBJECT_TYPE and FIRST/LAST_FUNCTION_CLASS_TYPE
to FIRST/LAST_[NON]CALLABLE_SPEC_OBJECT_TYPE for clarity.
* Eliminate the overlap over JS_REGEXP_TYPE.
* Also replace FIRST_JS_OBJECT with FIRST_JS_RECEIVER, but only use it where
we exclusively talk about the internal representation type.
* Insert JS_PROXY and JS_FUNCTION_PROXY in the appropriate places.
- Fix all checks concerning classification, especially for functions, to
use the CALLABLE_SPEC_OBJECT range (that includes funciton proxies).
- Handle proxies in SetProperty (that was the easiest part :) ).
- A few simple test cases.
R=kmillikin@chromium.org
Review URL: http://codereview.chromium.org/6992072
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8126 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2011-05-31 16:38:40 +00:00
|
|
|
DERIVED_SET_TRAP_INDEX,
|
2012-11-06 12:32:36 +00:00
|
|
|
PROXY_ENUMERATE_INDEX,
|
|
|
|
OBSERVERS_NOTIFY_CHANGE_INDEX,
|
2013-06-04 23:58:49 +00:00
|
|
|
OBSERVERS_ENQUEUE_SPLICE_INDEX,
|
|
|
|
OBSERVERS_BEGIN_SPLICE_INDEX,
|
|
|
|
OBSERVERS_END_SPLICE_INDEX,
|
2014-05-02 16:13:10 +00:00
|
|
|
NATIVE_OBJECT_OBSERVE_INDEX,
|
|
|
|
NATIVE_OBJECT_GET_NOTIFIER_INDEX,
|
|
|
|
NATIVE_OBJECT_NOTIFIER_PERFORM_CHANGE,
|
2014-03-11 14:41:22 +00:00
|
|
|
SLOPPY_GENERATOR_FUNCTION_MAP_INDEX,
|
|
|
|
STRICT_GENERATOR_FUNCTION_MAP_INDEX,
|
2015-02-25 14:52:36 +00:00
|
|
|
STRONG_GENERATOR_FUNCTION_MAP_INDEX,
|
2013-04-11 16:28:19 +00:00
|
|
|
GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
|
2014-04-17 17:45:32 +00:00
|
|
|
ITERATOR_RESULT_MAP_INDEX,
|
|
|
|
MAP_ITERATOR_MAP_INDEX,
|
|
|
|
SET_ITERATOR_MAP_INDEX,
|
2014-08-25 09:12:22 +00:00
|
|
|
ARRAY_VALUES_ITERATOR_INDEX,
|
2014-11-12 11:34:09 +00:00
|
|
|
SCRIPT_CONTEXT_TABLE_INDEX,
|
2014-11-10 18:03:50 +00:00
|
|
|
MAP_CACHE_INDEX,
|
2014-12-15 19:08:32 +00:00
|
|
|
TO_LENGTH_FUN_INDEX,
|
2010-10-18 14:59:03 +00:00
|
|
|
|
|
|
|
// Properties from here are treated as weak references by the full GC.
|
|
|
|
// Scavenge treats them as strong references.
|
2010-12-07 11:31:57 +00:00
|
|
|
OPTIMIZED_FUNCTIONS_LIST, // Weak.
|
2013-09-04 13:53:24 +00:00
|
|
|
OPTIMIZED_CODE_LIST, // Weak.
|
|
|
|
DEOPTIMIZED_CODE_LIST, // Weak.
|
|
|
|
NEXT_CONTEXT_LINK, // Weak.
|
2010-10-18 14:59:03 +00:00
|
|
|
|
|
|
|
// Total number of slots.
|
2012-08-17 09:03:08 +00:00
|
|
|
NATIVE_CONTEXT_SLOTS,
|
2010-12-07 11:31:57 +00:00
|
|
|
FIRST_WEAK_SLOT = OPTIMIZED_FUNCTIONS_LIST
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Direct slot access.
|
|
|
|
JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); }
|
|
|
|
void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); }
|
|
|
|
|
|
|
|
Context* previous() {
|
2008-10-24 10:59:40 +00:00
|
|
|
Object* result = unchecked_previous();
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(IsBootstrappingOrValidParentContext(result, this));
|
2008-10-24 10:59:40 +00:00
|
|
|
return reinterpret_cast<Context*>(result);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
|
|
|
void set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
|
|
|
|
|
2011-06-16 06:37:49 +00:00
|
|
|
bool has_extension() { return extension() != NULL; }
|
|
|
|
Object* extension() { return get(EXTENSION_INDEX); }
|
|
|
|
void set_extension(Object* object) { set(EXTENSION_INDEX, object); }
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2012-07-09 08:59:03 +00:00
|
|
|
JSModule* module() { return JSModule::cast(get(EXTENSION_INDEX)); }
|
|
|
|
void set_module(JSModule* module) { set(EXTENSION_INDEX, module); }
|
|
|
|
|
2011-06-28 15:22:08 +00:00
|
|
|
// Get the context where var declarations will be hoisted to, which
|
|
|
|
// may be the context itself.
|
|
|
|
Context* declaration_context();
|
|
|
|
|
2012-08-17 12:59:00 +00:00
|
|
|
GlobalObject* global_object() {
|
|
|
|
Object* result = get(GLOBAL_OBJECT_INDEX);
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(IsBootstrappingOrGlobalObject(this->GetIsolate(), result));
|
2008-10-24 10:59:40 +00:00
|
|
|
return reinterpret_cast<GlobalObject*>(result);
|
2008-07-03 15:10:15 +00:00
|
|
|
}
|
2012-08-17 12:59:00 +00:00
|
|
|
void set_global_object(GlobalObject* object) {
|
|
|
|
set(GLOBAL_OBJECT_INDEX, object);
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
Split window support from V8.
Here is a description of the background and design of split window in Chrome and V8:
https://docs.google.com/a/google.com/Doc?id=chhjkpg_47fwddxbfr
This change list splits the window object into two parts: 1) an inner window object used as the global object of contexts; 2) an outer window object exposed to JavaScript and accessible by the name 'window'. Firefox did it awhile ago, here are some discussions: https://wiki.mozilla.org/Gecko:SplitWindow. One additional benefit of splitting window in Chrome is that accessing global variables don't need security checks anymore, it can improve applications that use many global variables.
V8 support of split window:
There are a small number of changes on V8 api to support split window:
Security context is removed from V8, so does related API functions;
A global object can be detached from its context and reused by a new context;
Access checks on an object template can be turned on/off by default;
An object can turn on its access checks later;
V8 has a new object type, ApiGlobalObject, which is the outer window object type. The existing JSGlobalObject becomes the inner window object type. Security checks are moved from JSGlobalObject to ApiGlobalObject. ApiGlobalObject is the one exposed to JavaScript, it is accessible through Context::Global(). ApiGlobalObject's prototype is set to JSGlobalObject so that property lookups are forwarded to JSGlobalObject. ApiGlobalObject forwards all other property access requests to JSGlobalObject, such as SetProperty, DeleteProperty, etc.
Security token is moved to a global context, and ApiGlobalObject has a reference to its global context. JSGlobalObject has a reference to its global context as well. When accessing properties on a global object in JavaScript, the domain security check is performed by comparing the security token of the lexical context (Top::global_context()) to the token of global object's context. The check is only needed when the receiver is a window object, such as 'window.document'. Accessing global variables, such as 'var foo = 3; foo' does not need checks because the receiver is the inner window object.
When an outer window is detached from its global context (when a frame navigates away from a page), it is completely detached from the inner window. A new context is created for the new page, and the outer global object is reused. At this point, the access check on the DOMWindow wrapper of the old context is turned on. The code in old context is still able to access DOMWindow properties, but it has to go through domain security checks.
It is debatable on how to implement the outer window object. Currently each property access function has to check if the receiver is ApiGlobalObject type. This approach might be error-prone that one may forget to check the receiver when adding new functions. It is unlikely a performance issue because accessing global variables are more common than 'window.foo' style coding.
I am still working on the ARM port, and I'd like to hear comments and suggestions on the best way to support it in V8.
Review URL: http://codereview.chromium.org/7366
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@540 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2008-10-21 19:07:58 +00:00
|
|
|
// Returns a JSGlobalProxy object or null.
|
|
|
|
JSObject* global_proxy();
|
|
|
|
void set_global_proxy(JSObject* global);
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// The builtins object.
|
|
|
|
JSBuiltinsObject* builtins();
|
|
|
|
|
2014-11-12 11:34:09 +00:00
|
|
|
// Get the script context by traversing the context chain.
|
|
|
|
Context* script_context();
|
Get rid of static module allocation, do it in code.
Modules now have their own local scope, represented by their own context.
Module instance objects have an accessor for every export that forwards
access to the respective slot from the module's context. (Exports that are
modules themselves, however, are simple data properties.)
All modules have a _hosting_ scope/context, which (currently) is the
(innermost) enclosing global scope. To deal with recursion, nested modules
are hosted by the same scope as global ones.
For every (global or nested) module literal, the hosting context has an
internal slot that points directly to the respective module context. This
enables quick access to (statically resolved) module members by 2-dimensional
access through the hosting context. For example,
module A {
let x;
module B { let y; }
}
module C { let z; }
allocates contexts as follows:
[header| .A | .B | .C | A | C ] (global)
| | |
| | +-- [header| z ] (module)
| |
| +------- [header| y ] (module)
|
+------------ [header| x | B ] (module)
Here, .A, .B, .C are the internal slots pointing to the hosted module
contexts, whereas A, B, C hold the actual instance objects (note that every
module context also points to the respective instance object through its
extension slot in the header).
To deal with arbitrary recursion and aliases between modules,
they are created and initialized in several stages. Each stage applies to
all modules in the hosting global scope, including nested ones.
1. Allocate: for each module _literal_, allocate the module contexts and
respective instance object and wire them up. This happens in the
PushModuleContext runtime function, as generated by AllocateModules
(invoked by VisitDeclarations in the hosting scope).
2. Bind: for each module _declaration_ (i.e. literals as well as aliases),
assign the respective instance object to respective local variables. This
happens in VisitModuleDeclaration, and uses the instance objects created
in the previous stage.
For each module _literal_, this phase also constructs a module descriptor
for the next stage. This happens in VisitModuleLiteral.
3. Populate: invoke the DeclareModules runtime function to populate each
_instance_ object with accessors for it exports. This is generated by
DeclareModules (invoked by VisitDeclarations in the hosting scope again),
and uses the descriptors generated in the previous stage.
4. Initialize: execute the module bodies (and other code) in sequence. This
happens by the separate statements generated for module bodies. To reenter
the module scopes properly, the parser inserted ModuleStatements.
R=mstarzinger@chromium.org,svenpanne@chromium.org
BUG=
Review URL: https://codereview.chromium.org/11093074
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13033 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
2012-11-22 10:25:22 +00:00
|
|
|
|
2012-08-17 09:03:08 +00:00
|
|
|
// Compute the native context by traversing the context chain.
|
|
|
|
Context* native_context();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2012-12-07 10:35:50 +00:00
|
|
|
// Predicates for context types. IsNativeContext is also defined on Object
|
2012-08-17 09:03:08 +00:00
|
|
|
// because we frequently have to know if arbitrary objects are natives
|
2011-06-09 11:26:01 +00:00
|
|
|
// contexts.
|
2012-12-07 10:35:50 +00:00
|
|
|
bool IsNativeContext() {
|
|
|
|
Map* map = this->map();
|
|
|
|
return map == map->GetHeap()->native_context_map();
|
|
|
|
}
|
2011-06-09 11:26:01 +00:00
|
|
|
bool IsFunctionContext() {
|
|
|
|
Map* map = this->map();
|
|
|
|
return map == map->GetHeap()->function_context_map();
|
|
|
|
}
|
|
|
|
bool IsCatchContext() {
|
|
|
|
Map* map = this->map();
|
|
|
|
return map == map->GetHeap()->catch_context_map();
|
|
|
|
}
|
2011-06-16 06:37:49 +00:00
|
|
|
bool IsWithContext() {
|
|
|
|
Map* map = this->map();
|
|
|
|
return map == map->GetHeap()->with_context_map();
|
|
|
|
}
|
2011-08-11 16:29:28 +00:00
|
|
|
bool IsBlockContext() {
|
|
|
|
Map* map = this->map();
|
|
|
|
return map == map->GetHeap()->block_context_map();
|
|
|
|
}
|
2012-02-20 14:02:59 +00:00
|
|
|
bool IsModuleContext() {
|
|
|
|
Map* map = this->map();
|
|
|
|
return map == map->GetHeap()->module_context_map();
|
|
|
|
}
|
2014-11-12 11:34:09 +00:00
|
|
|
bool IsScriptContext() {
|
2012-08-27 09:40:26 +00:00
|
|
|
Map* map = this->map();
|
2014-11-12 11:34:09 +00:00
|
|
|
return map == map->GetHeap()->script_context_map();
|
2012-08-27 09:40:26 +00:00
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2014-05-19 13:45:45 +00:00
|
|
|
bool HasSameSecurityTokenAs(Context* that) {
|
|
|
|
return this->global_object()->native_context()->security_token() ==
|
|
|
|
that->global_object()->native_context()->security_token();
|
|
|
|
}
|
|
|
|
|
2013-09-04 13:53:24 +00:00
|
|
|
// A native context holds a list of all functions with optimized code.
|
2010-12-07 11:31:57 +00:00
|
|
|
void AddOptimizedFunction(JSFunction* function);
|
|
|
|
void RemoveOptimizedFunction(JSFunction* function);
|
2013-09-04 13:53:24 +00:00
|
|
|
void SetOptimizedFunctionsListHead(Object* head);
|
2010-12-07 11:31:57 +00:00
|
|
|
Object* OptimizedFunctionsListHead();
|
2013-09-04 13:53:24 +00:00
|
|
|
|
|
|
|
// The native context also stores a list of all optimized code and a
|
|
|
|
// list of all deoptimized code, which are needed by the deoptimizer.
|
|
|
|
void AddOptimizedCode(Code* code);
|
|
|
|
void SetOptimizedCodeListHead(Object* head);
|
|
|
|
Object* OptimizedCodeListHead();
|
|
|
|
void SetDeoptimizedCodeListHead(Object* head);
|
|
|
|
Object* DeoptimizedCodeListHead();
|
2010-12-07 11:31:57 +00:00
|
|
|
|
2012-09-17 09:58:22 +00:00
|
|
|
Handle<Object> ErrorMessageForCodeGenerationFromStrings();
|
|
|
|
|
2012-08-17 09:03:08 +00:00
|
|
|
#define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
|
2008-07-03 15:10:15 +00:00
|
|
|
void set_##name(type* value) { \
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(IsNativeContext()); \
|
2008-07-03 15:10:15 +00:00
|
|
|
set(index, value); \
|
|
|
|
} \
|
2013-05-13 07:35:26 +00:00
|
|
|
bool is_##name(type* value) { \
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(IsNativeContext()); \
|
2013-05-13 07:35:26 +00:00
|
|
|
return type::cast(get(index)) == value; \
|
|
|
|
} \
|
2008-07-03 15:10:15 +00:00
|
|
|
type* name() { \
|
2014-08-04 11:34:54 +00:00
|
|
|
DCHECK(IsNativeContext()); \
|
2008-07-03 15:10:15 +00:00
|
|
|
return type::cast(get(index)); \
|
|
|
|
}
|
2012-08-17 09:03:08 +00:00
|
|
|
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
|
|
|
|
#undef NATIVE_CONTEXT_FIELD_ACCESSORS
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2012-04-16 13:20:50 +00:00
|
|
|
// Lookup the slot called name, starting with the current context.
|
2011-09-21 08:51:44 +00:00
|
|
|
// There are three possibilities:
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
2011-09-21 08:51:44 +00:00
|
|
|
// 1) result->IsContext():
|
|
|
|
// The binding was found in a context. *index is always the
|
|
|
|
// non-negative slot index. *attributes is NONE for var and let
|
|
|
|
// declarations, READ_ONLY for const declarations (never ABSENT).
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
2011-09-21 08:51:44 +00:00
|
|
|
// 2) result->IsJSObject():
|
|
|
|
// The binding was found as a named property in a context extension
|
|
|
|
// object (i.e., was introduced via eval), as a property on the subject
|
|
|
|
// of with, or as a property of the global object. *index is -1 and
|
|
|
|
// *attributes is not ABSENT.
|
2008-07-03 15:10:15 +00:00
|
|
|
//
|
2011-09-21 08:51:44 +00:00
|
|
|
// 3) result.is_null():
|
|
|
|
// There was no binding found, *index is always -1 and *attributes is
|
|
|
|
// always ABSENT.
|
2011-08-30 11:23:57 +00:00
|
|
|
Handle<Object> Lookup(Handle<String> name,
|
|
|
|
ContextLookupFlags flags,
|
2011-09-21 08:51:44 +00:00
|
|
|
int* index,
|
2011-08-30 11:23:57 +00:00
|
|
|
PropertyAttributes* attributes,
|
|
|
|
BindingFlags* binding_flags);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Code generation support.
|
|
|
|
static int SlotOffset(int index) {
|
|
|
|
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
|
|
|
|
}
|
2008-10-24 10:59:40 +00:00
|
|
|
|
2015-02-04 09:34:05 +00:00
|
|
|
static int FunctionMapIndex(LanguageMode language_mode, FunctionKind kind) {
|
2014-09-10 16:39:42 +00:00
|
|
|
if (IsGeneratorFunction(kind)) {
|
2015-02-25 14:52:36 +00:00
|
|
|
return is_strong(language_mode) ? STRONG_GENERATOR_FUNCTION_MAP_INDEX :
|
|
|
|
is_strict(language_mode) ? STRICT_GENERATOR_FUNCTION_MAP_INDEX
|
2015-02-04 09:34:05 +00:00
|
|
|
: SLOPPY_GENERATOR_FUNCTION_MAP_INDEX;
|
2014-09-10 16:39:42 +00:00
|
|
|
}
|
|
|
|
|
2015-02-25 14:52:36 +00:00
|
|
|
if (IsConstructor(kind)) {
|
2015-04-09 22:40:16 +00:00
|
|
|
// Use strict function map (no own "caller" / "arguments")
|
|
|
|
return is_strong(language_mode) ? STRONG_CONSTRUCTOR_MAP_INDEX
|
|
|
|
: STRICT_FUNCTION_MAP_INDEX;
|
2015-02-25 14:52:36 +00:00
|
|
|
}
|
|
|
|
|
2015-02-05 23:34:16 +00:00
|
|
|
if (IsArrowFunction(kind) || IsConciseMethod(kind) ||
|
|
|
|
IsAccessorFunction(kind)) {
|
2015-04-09 22:40:16 +00:00
|
|
|
return is_strong(language_mode)
|
|
|
|
? STRONG_FUNCTION_MAP_INDEX
|
|
|
|
: STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
|
2014-09-10 16:39:42 +00:00
|
|
|
}
|
|
|
|
|
2015-02-25 14:52:36 +00:00
|
|
|
return is_strong(language_mode) ? STRONG_FUNCTION_MAP_INDEX :
|
|
|
|
is_strict(language_mode) ? STRICT_FUNCTION_MAP_INDEX
|
2015-02-04 09:34:05 +00:00
|
|
|
: SLOPPY_FUNCTION_MAP_INDEX;
|
2013-04-11 16:28:19 +00:00
|
|
|
}
|
|
|
|
|
2012-08-17 09:03:08 +00:00
|
|
|
static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;
|
2010-10-18 14:59:03 +00:00
|
|
|
|
|
|
|
// GC support.
|
|
|
|
typedef FixedBodyDescriptor<
|
|
|
|
kHeaderSize, kSize, kSize> ScavengeBodyDescriptor;
|
|
|
|
|
|
|
|
typedef FixedBodyDescriptor<
|
|
|
|
kHeaderSize,
|
|
|
|
kHeaderSize + FIRST_WEAK_SLOT * kPointerSize,
|
|
|
|
kSize> MarkCompactBodyDescriptor;
|
|
|
|
|
2008-10-24 10:59:40 +00:00
|
|
|
private:
|
|
|
|
// Unchecked access to the slots.
|
|
|
|
Object* unchecked_previous() { return get(PREVIOUS_INDEX); }
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Bootstrapping-aware type checks.
|
2012-07-09 08:59:03 +00:00
|
|
|
static bool IsBootstrappingOrValidParentContext(Object* object, Context* kid);
|
2013-09-03 06:57:16 +00:00
|
|
|
static bool IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object);
|
2008-10-24 10:59:40 +00:00
|
|
|
#endif
|
2012-11-13 12:27:03 +00:00
|
|
|
|
2014-05-27 13:43:29 +00:00
|
|
|
STATIC_ASSERT(kHeaderSize == Internals::kContextHeaderSize);
|
|
|
|
STATIC_ASSERT(EMBEDDER_DATA_INDEX == Internals::kContextEmbedderDataIndex);
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_CONTEXTS_H_
|