v8/src/contexts.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

731 lines
40 KiB
C
Raw Normal View History

// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CONTEXTS_H_
#define V8_CONTEXTS_H_
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class JSGlobalObject;
class JSGlobalProxy;
class MicrotaskQueue;
class NativeContext;
class RegExpMatchInfo;
enum ContextLookupFlags {
FOLLOW_CONTEXT_CHAIN = 1 << 0,
FOLLOW_PROTOTYPE_CHAIN = 1 << 1,
STOP_AT_DECLARATION_SCOPE = 1 << 2,
SKIP_WITH_CONTEXT = 1 << 3,
DONT_FOLLOW_CHAINS = 0,
FOLLOW_CHAINS = FOLLOW_CONTEXT_CHAIN | FOLLOW_PROTOTYPE_CHAIN,
};
// Heap-allocated activation contexts.
//
// Contexts are implemented as FixedArray-like objects having a fixed
// header with a set of common fields.
//
// Note: Context must have no virtual functions and Context objects
// must always be allocated via Heap::AllocateContext() or
// Factory::NewContext.
[async] Introduce dedicated JSAsyncFunctionObject. This JSAsyncFunctionObject represents the implicit generator object inside of async functions, and also holds the outer promise for the async functions. This in turn allows us to get rid of the .promise in the Parser / BytecodeGenerator completely, and will make it possible to build zero-cost async stack traces independent of the concrete synchronous part of the stack frame (which currently breaks in Node.js). In the bytecode all the async function operations now take this new JSAsyncFunctionObject instead of passing both the .generator_object and the .promise, which further simplifies and shrinks the bytecode. It also reduces the size of async function frames, potentially making the suspend/resume cheaper. This also changes `await` to use intrinsics instead of calling to special JSFunctions on the native context, and thus reduces the size of the native contexts. Drive-by-fix: Introduce a dedicated JSCreateAsyncFunctionObject operator to TurboFan. Bug: v8:7253, v8:7522 Change-Id: I2305302285156aa1f71328ecac70377abdd92c80 Ref: nodejs/node#11865 Design-Document: http://bit.ly/v8-zero-cost-async-stack-traces Reviewed-on: https://chromium-review.googlesource.com/c/1273049 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Cr-Commit-Position: refs/heads/master@{#56554}
2018-10-11 08:35:56 +00:00
#define NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
V(ASYNC_FUNCTION_PROMISE_CREATE_INDEX, JSFunction, \
async_function_promise_create) \
V(IS_ARRAYLIKE, JSFunction, is_arraylike) \
V(GENERATOR_NEXT_INTERNAL, JSFunction, generator_next_internal) \
V(MAKE_ERROR_INDEX, JSFunction, make_error) \
V(MAKE_RANGE_ERROR_INDEX, JSFunction, make_range_error) \
V(MAKE_SYNTAX_ERROR_INDEX, JSFunction, make_syntax_error) \
V(MAKE_TYPE_ERROR_INDEX, JSFunction, make_type_error) \
V(MAKE_URI_ERROR_INDEX, JSFunction, make_uri_error) \
V(OBJECT_CREATE, JSFunction, object_create) \
V(OBJECT_DEFINE_PROPERTIES, JSFunction, object_define_properties) \
V(OBJECT_DEFINE_PROPERTY, JSFunction, object_define_property) \
V(OBJECT_GET_PROTOTYPE_OF, JSFunction, object_get_prototype_of) \
V(OBJECT_IS_EXTENSIBLE, JSFunction, object_is_extensible) \
V(OBJECT_IS_FROZEN, JSFunction, object_is_frozen) \
V(OBJECT_IS_SEALED, JSFunction, object_is_sealed) \
V(OBJECT_KEYS, JSFunction, object_keys) \
V(REGEXP_INTERNAL_MATCH, JSFunction, regexp_internal_match) \
V(REFLECT_APPLY_INDEX, JSFunction, reflect_apply) \
V(REFLECT_CONSTRUCT_INDEX, JSFunction, reflect_construct) \
V(REFLECT_DEFINE_PROPERTY_INDEX, JSFunction, reflect_define_property) \
V(REFLECT_DELETE_PROPERTY_INDEX, JSFunction, reflect_delete_property) \
V(MATH_FLOOR_INDEX, JSFunction, math_floor) \
V(MATH_POW_INDEX, JSFunction, math_pow) \
V(NEW_PROMISE_CAPABILITY_INDEX, JSFunction, new_promise_capability) \
V(PROMISE_INTERNAL_CONSTRUCTOR_INDEX, JSFunction, \
promise_internal_constructor) \
V(IS_PROMISE_INDEX, JSFunction, is_promise) \
V(PROMISE_THEN_INDEX, JSFunction, promise_then)
#define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \
V(ARRAY_ENTRIES_ITERATOR_INDEX, JSFunction, array_entries_iterator) \
V(ARRAY_FOR_EACH_ITERATOR_INDEX, JSFunction, array_for_each_iterator) \
V(ARRAY_KEYS_ITERATOR_INDEX, JSFunction, array_keys_iterator) \
V(ARRAY_VALUES_ITERATOR_INDEX, JSFunction, array_values_iterator) \
V(ERROR_FUNCTION_INDEX, JSFunction, error_function) \
V(ERROR_TO_STRING, JSFunction, error_to_string) \
V(EVAL_ERROR_FUNCTION_INDEX, JSFunction, eval_error_function) \
V(GLOBAL_EVAL_FUN_INDEX, JSFunction, global_eval_fun) \
V(GLOBAL_PROXY_FUNCTION_INDEX, JSFunction, global_proxy_function) \
V(MAP_DELETE_INDEX, JSFunction, map_delete) \
V(MAP_GET_INDEX, JSFunction, map_get) \
V(MAP_HAS_INDEX, JSFunction, map_has) \
V(MAP_SET_INDEX, JSFunction, map_set) \
V(FUNCTION_HAS_INSTANCE_INDEX, JSFunction, function_has_instance) \
V(OBJECT_VALUE_OF, JSFunction, object_value_of) \
V(OBJECT_TO_STRING, JSFunction, object_to_string) \
V(PROMISE_ALL_INDEX, JSFunction, promise_all) \
V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
V(PROMISE_FUNCTION_INDEX, JSFunction, promise_function) \
V(RANGE_ERROR_FUNCTION_INDEX, JSFunction, range_error_function) \
V(REFERENCE_ERROR_FUNCTION_INDEX, JSFunction, reference_error_function) \
V(SET_ADD_INDEX, JSFunction, set_add) \
V(SET_DELETE_INDEX, JSFunction, set_delete) \
V(SET_HAS_INDEX, JSFunction, set_has) \
V(SYNTAX_ERROR_FUNCTION_INDEX, JSFunction, syntax_error_function) \
V(TYPE_ERROR_FUNCTION_INDEX, JSFunction, type_error_function) \
V(URI_ERROR_FUNCTION_INDEX, JSFunction, uri_error_function) \
V(WASM_COMPILE_ERROR_FUNCTION_INDEX, JSFunction, \
wasm_compile_error_function) \
V(WASM_LINK_ERROR_FUNCTION_INDEX, JSFunction, wasm_link_error_function) \
V(WASM_RUNTIME_ERROR_FUNCTION_INDEX, JSFunction, \
wasm_runtime_error_function) \
V(WEAKMAP_SET_INDEX, JSFunction, weakmap_set) \
V(WEAKMAP_GET_INDEX, JSFunction, weakmap_get) \
V(WEAKSET_ADD_INDEX, JSFunction, weakset_add)
#define NATIVE_CONTEXT_FIELDS(V) \
V(GLOBAL_PROXY_INDEX, JSGlobalProxy, global_proxy_object) \
/* TODO(ishell): Actually we store exactly EmbedderDataArray here but */ \
/* it's already UBSan-fiendly and doesn't require a star... So declare */ \
/* it as a HeapObject for now. */ \
V(EMBEDDER_DATA_INDEX, HeapObject, embedder_data) \
/* Below is alpha-sorted */ \
V(ACCESSOR_PROPERTY_DESCRIPTOR_MAP_INDEX, Map, \
accessor_property_descriptor_map) \
V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
V(ARRAY_BUFFER_FUN_INDEX, JSFunction, array_buffer_fun) \
V(ARRAY_BUFFER_MAP_INDEX, Map, array_buffer_map) \
V(ARRAY_BUFFER_NOINIT_FUN_INDEX, JSFunction, array_buffer_noinit_fun) \
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
V(ARRAY_JOIN_STACK_INDEX, HeapObject, array_join_stack) \
V(ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX, Map, async_from_sync_iterator_map) \
V(ASYNC_FUNCTION_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \
async_function_await_reject_shared_fun) \
V(ASYNC_FUNCTION_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
async_function_await_resolve_shared_fun) \
V(ASYNC_FUNCTION_FUNCTION_INDEX, JSFunction, async_function_constructor) \
[async] Improve async function handling. This change introduces new intrinsics used to desugar async functions in the Parser and the BytecodeGenerator, namely we introduce a new %_AsyncFunctionEnter intrinsic that constructs the generator object for the async function (and in the future will also create the outer promise for the async function). This generator object is internal and never escapes to user code, plus since async functions don't have a "prototype" property, we can just a single map here instead of tracking the prototype/initial_map on every async function. This saves one word per async function plus one initial_map per async function that was invoked at least once. We also introduce two new intrinsics %_AsyncFunctionReject, which rejects the outer promise with the caught exception, and another %_AsyncFunctionResolve, which resolves the outer promise with the right hand side of the `return` statement. These functions also perform the DevTools part of the job (aka popping from the promise stack and sending the debug event). This allows us to get rid of the implicit try-finally from async functions completely; because the finally block only called to the %AsyncFunctionPromiseRelease builtin, which was used to inform DevTools. In essence we now turn an async function like ```js async function f(x) { return await bar(x); } ``` into something like this (in Parser and BytecodeGenerator respectively): ``` function f(x) { .generator_object = %_AsyncFunctionEnter(.closure, this); .promise = %AsyncFunctionCreatePromise(); try { .tmp = await bar(x); return %_AsyncFunctionResolve(.promise, .tmp); } catch (e) { return %_AsyncFunctionReject(.promise, e); } } ``` Overall the bytecode for async functions gets significantly shorter already (and will get even shorter once we put the outer promise into the async function generator object). For example the bytecode for a simple async function ```js async function f(x) { return await x; } ``` goes from 175 bytes to 110 bytes (a ~38% reduction in size), which is in particular due to the simplification around the try-finally removal. Overall this seems to improve the doxbee-async-es2017-native test by around 2-3%. On the test case mentioned in v8:8276 we go from 1124ms to 441ms, which corresponds to a 60% reduction in total execution time! Tbr: marja@chromium.org Bug: v8:7253, v8:7522, v8:8276 Cq-Include-Trybots: luci.chromium.try:linux_chromium_headless_rel;luci.chromium.try:linux_chromium_rel_ng;master.tryserver.blink:linux_trusty_blink_rel Change-Id: Id29dc92de7490b387ff697860c900cee44c9a7a4 Reviewed-on: https://chromium-review.googlesource.com/c/1269041 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#56502}
2018-10-10 05:54:39 +00:00
V(ASYNC_FUNCTION_OBJECT_MAP_INDEX, Map, async_function_object_map) \
[async-iteration] implement AsyncGenerator - Introduce new struct AsyncGeneratorRequest, which holds information pertinent to resuming execution of an AsyncGenerator, such as the Promise associated with the async generator request. It is intended to be used as a singly linked list, and holds a pointer to the next item in te queue. - Introduce JSAsyncGeneratorObject (subclass of JSGeneratorObject), which includes several new internal fields (`queue` which contains a singly linked list of AsyncGeneratorRequest objects, and `await_input` which contains the sent value from an Await expression (This is necessary to prevent function.sent (used by yield*) from having the sent value observably overwritten during execution). - Modify SuspendGenerator to accept a set of Flags, which indicate whether the suspend is for a Yield or Await, and whether it takes place on an async generator or ES6 generator. - Introduce interpreter intrinsics and TF intrinsic lowering for accessing the await input of an async generator - Modify the JSGeneratorStore operator to understand whether or not it's suspending for a normal yield, or an AsyncGenerator Await. This ensures appropriate registers are stored. - Add versions of ResumeGeneratorTrampoline which store the input value in a different field depending on wether it's an AsyncGenerator Await resume, or an ordinary resume. Also modifies whether debug code will assert that the generator object is a JSGeneratorObject or a JSAsyncGeneratorObject depending on the resume type. BUG=v8:5855 R=bmeurer@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org, littledan@chromium.org, neis@chromium.org TBR=marja@chromium.org Change-Id: I9d58df1d344465fc937fe7eed322424204497187 Reviewed-on: https://chromium-review.googlesource.com/446961 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Hannes Payer <hpayer@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#44240}
2017-03-29 13:41:45 +00:00
V(ASYNC_GENERATOR_FUNCTION_FUNCTION_INDEX, JSFunction, \
async_generator_function_function) \
V(ASYNC_ITERATOR_VALUE_UNWRAP_SHARED_FUN, SharedFunctionInfo, \
async_iterator_value_unwrap_shared_fun) \
V(ASYNC_GENERATOR_AWAIT_REJECT_SHARED_FUN, SharedFunctionInfo, \
async_generator_await_reject_shared_fun) \
V(ASYNC_GENERATOR_AWAIT_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
async_generator_await_resolve_shared_fun) \
V(ASYNC_GENERATOR_YIELD_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
async_generator_yield_resolve_shared_fun) \
V(ASYNC_GENERATOR_RETURN_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
async_generator_return_resolve_shared_fun) \
V(ASYNC_GENERATOR_RETURN_CLOSED_RESOLVE_SHARED_FUN, SharedFunctionInfo, \
async_generator_return_closed_resolve_shared_fun) \
V(ASYNC_GENERATOR_RETURN_CLOSED_REJECT_SHARED_FUN, SharedFunctionInfo, \
async_generator_return_closed_reject_shared_fun) \
V(ATOMICS_OBJECT, JSObject, atomics_object) \
V(BIGINT_FUNCTION_INDEX, JSFunction, bigint_function) \
V(BIGINT64_ARRAY_FUN_INDEX, JSFunction, bigint64_array_fun) \
V(BIGUINT64_ARRAY_FUN_INDEX, JSFunction, biguint64_array_fun) \
V(BOOLEAN_FUNCTION_INDEX, JSFunction, boolean_function) \
V(BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX, Map, \
bound_function_with_constructor_map) \
V(BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX, Map, \
bound_function_without_constructor_map) \
V(CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, JSFunction, \
call_as_constructor_delegate) \
V(CALL_AS_FUNCTION_DELEGATE_INDEX, JSFunction, call_as_function_delegate) \
V(CALLSITE_FUNCTION_INDEX, JSFunction, callsite_function) \
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
V(DATA_PROPERTY_DESCRIPTOR_MAP_INDEX, Map, data_property_descriptor_map) \
V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \
V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
V(DEBUG_CONTEXT_ID_INDEX, Object, debug_context_id) \
V(EMPTY_FUNCTION_INDEX, JSFunction, empty_function) \
V(ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX, Object, \
error_message_for_code_gen_from_strings) \
V(ERRORS_THROWN_INDEX, Smi, errors_thrown) \
V(EXTRAS_EXPORTS_OBJECT_INDEX, JSObject, extras_binding_object) \
V(EXTRAS_UTILS_OBJECT_INDEX, Object, extras_utils_object) \
V(FAST_ALIASED_ARGUMENTS_MAP_INDEX, Map, fast_aliased_arguments_map) \
V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_INDEX, FixedArray, \
fast_template_instantiations_cache) \
V(FLOAT32_ARRAY_FUN_INDEX, JSFunction, float32_array_fun) \
V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \
V(FUNCTION_FUNCTION_INDEX, JSFunction, function_function) \
V(GENERATOR_FUNCTION_FUNCTION_INDEX, JSFunction, \
generator_function_function) \
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, generator_object_prototype_map) \
[async-iteration] implement AsyncGenerator - Introduce new struct AsyncGeneratorRequest, which holds information pertinent to resuming execution of an AsyncGenerator, such as the Promise associated with the async generator request. It is intended to be used as a singly linked list, and holds a pointer to the next item in te queue. - Introduce JSAsyncGeneratorObject (subclass of JSGeneratorObject), which includes several new internal fields (`queue` which contains a singly linked list of AsyncGeneratorRequest objects, and `await_input` which contains the sent value from an Await expression (This is necessary to prevent function.sent (used by yield*) from having the sent value observably overwritten during execution). - Modify SuspendGenerator to accept a set of Flags, which indicate whether the suspend is for a Yield or Await, and whether it takes place on an async generator or ES6 generator. - Introduce interpreter intrinsics and TF intrinsic lowering for accessing the await input of an async generator - Modify the JSGeneratorStore operator to understand whether or not it's suspending for a normal yield, or an AsyncGenerator Await. This ensures appropriate registers are stored. - Add versions of ResumeGeneratorTrampoline which store the input value in a different field depending on wether it's an AsyncGenerator Await resume, or an ordinary resume. Also modifies whether debug code will assert that the generator object is a JSGeneratorObject or a JSAsyncGeneratorObject depending on the resume type. BUG=v8:5855 R=bmeurer@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org, littledan@chromium.org, neis@chromium.org TBR=marja@chromium.org Change-Id: I9d58df1d344465fc937fe7eed322424204497187 Reviewed-on: https://chromium-review.googlesource.com/446961 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Hannes Payer <hpayer@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#44240}
2017-03-29 13:41:45 +00:00
V(ASYNC_GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \
async_generator_object_prototype_map) \
[es2015] Refactor the JSArrayIterator. This changes the JSArrayIterator to always have only a single instance type, instead of the zoo of instance types that we had before, and which became less useful with the specification update to when "next" is loaded from the iterator now. This greatly simplifies the baseline implementation of the array iterator, which now only looks at the iterated object during %ArrayIteratorPrototype%.next invocations. In TurboFan we introduce a new JSCreateArrayIterator operator, that holds the IterationKind and get's the iterated object as input. When optimizing %ArrayIteratorPrototype%.next in the JSCallReducer, we check whether the receiver is a JSCreateArrayIterator, and if so, we try to infer maps for the iterated object from there. If we find any, we speculatively assume that these won't have changed during iteration (as we did before with the previous approach), and generate fast code for both JSArray and JSTypedArray iteration. Drive-by-fix: Drop the fast_array_iteration protector, it's not necessary anymore since we have the deoptimization guard bit in the JSCallReducer now. This addresses the performance cliff noticed in webpack 4. The minimal repro on the tracking bug goes from console.timeEnd: mono, 124.773000 console.timeEnd: poly, 670.353000 to console.timeEnd: mono, 118.709000 console.timeEnd: poly, 141.393000 so that's a 4.7x improvement. Also make presubmit happy by adding the missing #undef's. Bug: v8:7510, v7:7514 Change-Id: I79a46bfa2cd0f0710e09365ef72519b1bbb667b5 Reviewed-on: https://chromium-review.googlesource.com/946098 Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#51725}
2018-03-02 19:31:01 +00:00
V(INITIAL_ARRAY_ITERATOR_MAP_INDEX, Map, initial_array_iterator_map) \
V(INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX, JSObject, \
initial_array_iterator_prototype) \
V(INITIAL_ARRAY_PROTOTYPE_INDEX, JSObject, initial_array_prototype) \
V(INITIAL_ERROR_PROTOTYPE_INDEX, JSObject, initial_error_prototype) \
V(INITIAL_GENERATOR_PROTOTYPE_INDEX, JSObject, initial_generator_prototype) \
[async-iteration] implement AsyncGenerator - Introduce new struct AsyncGeneratorRequest, which holds information pertinent to resuming execution of an AsyncGenerator, such as the Promise associated with the async generator request. It is intended to be used as a singly linked list, and holds a pointer to the next item in te queue. - Introduce JSAsyncGeneratorObject (subclass of JSGeneratorObject), which includes several new internal fields (`queue` which contains a singly linked list of AsyncGeneratorRequest objects, and `await_input` which contains the sent value from an Await expression (This is necessary to prevent function.sent (used by yield*) from having the sent value observably overwritten during execution). - Modify SuspendGenerator to accept a set of Flags, which indicate whether the suspend is for a Yield or Await, and whether it takes place on an async generator or ES6 generator. - Introduce interpreter intrinsics and TF intrinsic lowering for accessing the await input of an async generator - Modify the JSGeneratorStore operator to understand whether or not it's suspending for a normal yield, or an AsyncGenerator Await. This ensures appropriate registers are stored. - Add versions of ResumeGeneratorTrampoline which store the input value in a different field depending on wether it's an AsyncGenerator Await resume, or an ordinary resume. Also modifies whether debug code will assert that the generator object is a JSGeneratorObject or a JSAsyncGeneratorObject depending on the resume type. BUG=v8:5855 R=bmeurer@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org, littledan@chromium.org, neis@chromium.org TBR=marja@chromium.org Change-Id: I9d58df1d344465fc937fe7eed322424204497187 Reviewed-on: https://chromium-review.googlesource.com/446961 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Hannes Payer <hpayer@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#44240}
2017-03-29 13:41:45 +00:00
V(INITIAL_ASYNC_GENERATOR_PROTOTYPE_INDEX, JSObject, \
initial_async_generator_prototype) \
V(INITIAL_ITERATOR_PROTOTYPE_INDEX, JSObject, initial_iterator_prototype) \
Add iterator protectors for JSMapIterator/JSSet/JSSetIterator. The MapIterator protector protects the original iteration behaviors of Map.prototype.keys(), Map.prototype.values(), and Set.prototype.entries(). It does not protect the original iteration behavior of Map.prototype[Symbol.iterator](). The protector is invalidated when: * The 'next' property is set on an object where the property holder is the %MapIteratorPrototype% (e.g. because the object is that very prototype). * The 'Symbol.iterator' property is set on an object where the property holder is the %IteratorPrototype%. Note that this also invalidates the SetIterator protector (see below). The SetIterator protector protects the original iteration behavior of Set.prototype.keys(), Set.prototype.values(), Set.prototype.entries(), and Set.prototype[Symbol.iterator](). The protector is invalidated when: * The 'next' property is set on an object where the property holder is the %SetIteratorPrototype% (e.g. because the object is that very prototype). * The 'Symbol.iterator' property is set on an object where the property holder is the %SetPrototype% OR %IteratorPrototype%. This means that setting Symbol.iterator on a MapIterator object can also invalidate the SetIterator protector, and vice versa, setting Symbol.iterator on a SetIterator object can also invalidate the MapIterator. This is an over- approximation for the sake of simplicity. Bug: v8:7980 Change-Id: I54ad6e4c7f19ccc27d7001f6c4b6c8d6ea4ee871 Reviewed-on: https://chromium-review.googlesource.com/c/1273102 Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Hai Dang <dhai@google.com> Cr-Commit-Position: refs/heads/master@{#56530}
2018-10-10 13:29:32 +00:00
V(INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX, JSObject, \
initial_map_iterator_prototype) \
V(INITIAL_MAP_PROTOTYPE_MAP_INDEX, Map, initial_map_prototype_map) \
V(INITIAL_OBJECT_PROTOTYPE_INDEX, JSObject, initial_object_prototype) \
Add iterator protectors for JSMapIterator/JSSet/JSSetIterator. The MapIterator protector protects the original iteration behaviors of Map.prototype.keys(), Map.prototype.values(), and Set.prototype.entries(). It does not protect the original iteration behavior of Map.prototype[Symbol.iterator](). The protector is invalidated when: * The 'next' property is set on an object where the property holder is the %MapIteratorPrototype% (e.g. because the object is that very prototype). * The 'Symbol.iterator' property is set on an object where the property holder is the %IteratorPrototype%. Note that this also invalidates the SetIterator protector (see below). The SetIterator protector protects the original iteration behavior of Set.prototype.keys(), Set.prototype.values(), Set.prototype.entries(), and Set.prototype[Symbol.iterator](). The protector is invalidated when: * The 'next' property is set on an object where the property holder is the %SetIteratorPrototype% (e.g. because the object is that very prototype). * The 'Symbol.iterator' property is set on an object where the property holder is the %SetPrototype% OR %IteratorPrototype%. This means that setting Symbol.iterator on a MapIterator object can also invalidate the SetIterator protector, and vice versa, setting Symbol.iterator on a SetIterator object can also invalidate the MapIterator. This is an over- approximation for the sake of simplicity. Bug: v8:7980 Change-Id: I54ad6e4c7f19ccc27d7001f6c4b6c8d6ea4ee871 Reviewed-on: https://chromium-review.googlesource.com/c/1273102 Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Hai Dang <dhai@google.com> Cr-Commit-Position: refs/heads/master@{#56530}
2018-10-10 13:29:32 +00:00
V(INITIAL_SET_ITERATOR_PROTOTYPE_INDEX, JSObject, \
initial_set_iterator_prototype) \
V(INITIAL_SET_PROTOTYPE_INDEX, JSObject, initial_set_prototype) \
V(INITIAL_SET_PROTOTYPE_MAP_INDEX, Map, initial_set_prototype_map) \
V(INITIAL_STRING_ITERATOR_MAP_INDEX, Map, initial_string_iterator_map) \
V(INITIAL_STRING_ITERATOR_PROTOTYPE_INDEX, JSObject, \
initial_string_iterator_prototype) \
V(INITIAL_STRING_PROTOTYPE_INDEX, JSObject, initial_string_prototype) \
V(INITIAL_WEAKMAP_PROTOTYPE_MAP_INDEX, Map, initial_weakmap_prototype_map) \
V(INITIAL_WEAKSET_PROTOTYPE_MAP_INDEX, Map, initial_weakset_prototype_map) \
V(INT16_ARRAY_FUN_INDEX, JSFunction, int16_array_fun) \
V(INT32_ARRAY_FUN_INDEX, JSFunction, int32_array_fun) \
V(INT8_ARRAY_FUN_INDEX, JSFunction, int8_array_fun) \
V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
V(INTL_COLLATOR_FUNCTION_INDEX, JSFunction, intl_collator_function) \
V(INTL_DATE_TIME_FORMAT_FUNCTION_INDEX, JSFunction, \
intl_date_time_format_function) \
V(INTL_NUMBER_FORMAT_FUNCTION_INDEX, JSFunction, \
intl_number_format_function) \
V(INTL_LOCALE_FUNCTION_INDEX, JSFunction, intl_locale_function) \
V(INTL_SEGMENT_ITERATOR_MAP_INDEX, Map, intl_segment_iterator_map) \
V(ITERATOR_RESULT_MAP_INDEX, Map, iterator_result_map) \
V(JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX, Map, \
js_array_packed_smi_elements_map) \
V(JS_ARRAY_HOLEY_SMI_ELEMENTS_MAP_INDEX, Map, \
js_array_holey_smi_elements_map) \
V(JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX, Map, js_array_packed_elements_map) \
V(JS_ARRAY_HOLEY_ELEMENTS_MAP_INDEX, Map, js_array_holey_elements_map) \
V(JS_ARRAY_PACKED_DOUBLE_ELEMENTS_MAP_INDEX, Map, \
js_array_packed_double_elements_map) \
V(JS_ARRAY_HOLEY_DOUBLE_ELEMENTS_MAP_INDEX, Map, \
js_array_holey_double_elements_map) \
V(JS_MAP_FUN_INDEX, JSFunction, js_map_fun) \
V(JS_MAP_MAP_INDEX, Map, js_map_map) \
V(JS_MODULE_NAMESPACE_MAP, Map, js_module_namespace_map) \
V(JS_SET_FUN_INDEX, JSFunction, js_set_fun) \
V(JS_SET_MAP_INDEX, Map, js_set_map) \
V(JS_WEAK_CELL_MAP_INDEX, Map, js_weak_cell_map) \
V(JS_WEAK_FACTORY_CLEANUP_ITERATOR_MAP_INDEX, Map, \
js_weak_factory_cleanup_iterator_map) \
V(JS_WEAK_MAP_FUN_INDEX, JSFunction, js_weak_map_fun) \
V(JS_WEAK_REF_MAP_INDEX, Map, js_weak_ref_map) \
V(JS_WEAK_SET_FUN_INDEX, JSFunction, js_weak_set_fun) \
V(MAP_CACHE_INDEX, Object, map_cache) \
V(MAP_KEY_ITERATOR_MAP_INDEX, Map, map_key_iterator_map) \
V(MAP_KEY_VALUE_ITERATOR_MAP_INDEX, Map, map_key_value_iterator_map) \
V(MAP_VALUE_ITERATOR_MAP_INDEX, Map, map_value_iterator_map) \
V(MATH_RANDOM_INDEX_INDEX, Smi, math_random_index) \
V(MATH_RANDOM_STATE_INDEX, ByteArray, math_random_state) \
V(MATH_RANDOM_CACHE_INDEX, FixedDoubleArray, math_random_cache) \
V(MESSAGE_LISTENERS_INDEX, TemplateList, message_listeners) \
V(NATIVES_UTILS_OBJECT_INDEX, Object, natives_utils_object) \
V(NORMALIZED_MAP_CACHE_INDEX, Object, normalized_map_cache) \
V(NUMBER_FUNCTION_INDEX, JSFunction, number_function) \
V(OBJECT_FUNCTION_INDEX, JSFunction, object_function) \
V(OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX, Map, object_function_prototype_map) \
V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \
V(PROXY_CALLABLE_MAP_INDEX, Map, proxy_callable_map) \
V(PROXY_CONSTRUCTOR_MAP_INDEX, Map, proxy_constructor_map) \
V(PROXY_FUNCTION_INDEX, JSFunction, proxy_function) \
V(PROXY_MAP_INDEX, Map, proxy_map) \
V(PROXY_REVOCABLE_RESULT_MAP_INDEX, Map, proxy_revocable_result_map) \
V(PROXY_REVOKE_SHARED_FUN, SharedFunctionInfo, proxy_revoke_shared_fun) \
V(PROMISE_GET_CAPABILITIES_EXECUTOR_SHARED_FUN, SharedFunctionInfo, \
promise_get_capabilities_executor_shared_fun) \
[builtins] Refactor the promise resolution and rejection logic. This introduces dedicated builtins - FulfillPromise, - RejectPromise, and - ResolvePromise, which perform the corresponding operations from the language specification, and removes the redundant entry points and the excessive inlining of these operations into other builtins. We also add the same logic on the C++ side, so that we don't need to go into JavaScript land when resolving/rejecting from the API. The C++ side has a complete implementation, including full support for the debugger and the current PromiseHook machinery. This is to avoid constantly crossing the boundary for those cases, and to also simplify the CSA side (and soon the TurboFan side), where we only do the fast-path and bail out to the runtime for the general handling. On top of this we introduce %_RejectPromise and %_ResolvePromise, which are entry points used by the bytecode and parser desugarings for async functions, and also used by the V8 Extras API. Thanks to this we can uniformly optimize these in TurboFan, where we have corresponding operators JSRejectPromise and JSResolvePromise, which currently just call into the builtins, but middle-term can be further optimized, i.e. to skip the "then" lookup for JSResolvePromise when we know something about the resolution. In TurboFan we can also already inline the default PromiseCapability [[Reject]] and [[Resolve]] functions, although this is not as effective as it can be right now, until we have inlining support for the Promise constructor (being worked on by petermarshall@ right now) and/or SFI based CALL_IC feedback. Overall this change is meant as a refactoring without significant performance impact anywhere; it seems to improve performance of simple async functions a bit, but otherwise is neutral. Bug: v8:7253 Change-Id: Id0b979f9b2843560e38cd8df4b02627dad4b6d8c Reviewed-on: https://chromium-review.googlesource.com/911632 Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#51260}
2018-02-12 19:10:29 +00:00
V(PROMISE_CAPABILITY_DEFAULT_REJECT_SHARED_FUN_INDEX, SharedFunctionInfo, \
promise_capability_default_reject_shared_fun) \
V(PROMISE_CAPABILITY_DEFAULT_RESOLVE_SHARED_FUN_INDEX, SharedFunctionInfo, \
promise_capability_default_resolve_shared_fun) \
V(PROMISE_THEN_FINALLY_SHARED_FUN, SharedFunctionInfo, \
promise_then_finally_shared_fun) \
V(PROMISE_CATCH_FINALLY_SHARED_FUN, SharedFunctionInfo, \
promise_catch_finally_shared_fun) \
V(PROMISE_VALUE_THUNK_FINALLY_SHARED_FUN, SharedFunctionInfo, \
promise_value_thunk_finally_shared_fun) \
V(PROMISE_THROWER_FINALLY_SHARED_FUN, SharedFunctionInfo, \
promise_thrower_finally_shared_fun) \
V(PROMISE_ALL_RESOLVE_ELEMENT_SHARED_FUN, SharedFunctionInfo, \
promise_all_resolve_element_shared_fun) \
V(PROMISE_PROTOTYPE_INDEX, JSObject, promise_prototype) \
V(REGEXP_EXEC_FUNCTION_INDEX, JSFunction, regexp_exec_function) \
V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
V(REGEXP_LAST_MATCH_INFO_INDEX, RegExpMatchInfo, regexp_last_match_info) \
V(REGEXP_INTERNAL_MATCH_INFO_INDEX, RegExpMatchInfo, \
regexp_internal_match_info) \
V(REGEXP_PROTOTYPE_MAP_INDEX, Map, regexp_prototype_map) \
V(INITIAL_REGEXP_STRING_ITERATOR_PROTOTYPE_MAP_INDEX, Map, \
initial_regexp_string_iterator_prototype_map) \
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map) \
V(REGEXP_PROTOTYPE_INDEX, JSObject, regexp_prototype) \
V(SCRIPT_CONTEXT_TABLE_INDEX, ScriptContextTable, script_context_table) \
V(SECURITY_TOKEN_INDEX, Object, security_token) \
V(SERIALIZED_OBJECTS, FixedArray, serialized_objects) \
V(SET_VALUE_ITERATOR_MAP_INDEX, Map, set_value_iterator_map) \
V(SET_KEY_VALUE_ITERATOR_MAP_INDEX, Map, set_key_value_iterator_map) \
V(SHARED_ARRAY_BUFFER_FUN_INDEX, JSFunction, shared_array_buffer_fun) \
V(SLOPPY_ARGUMENTS_MAP_INDEX, Map, sloppy_arguments_map) \
V(SLOW_ALIASED_ARGUMENTS_MAP_INDEX, Map, slow_aliased_arguments_map) \
V(STRICT_ARGUMENTS_MAP_INDEX, Map, strict_arguments_map) \
V(SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP, Map, \
slow_object_with_null_prototype_map) \
V(SLOW_OBJECT_WITH_OBJECT_PROTOTYPE_MAP, Map, \
slow_object_with_object_prototype_map) \
V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_INDEX, SimpleNumberDictionary, \
slow_template_instantiations_cache) \
/* All *_FUNCTION_MAP_INDEX definitions used by Context::FunctionMapIndex */ \
/* must remain together. */ \
V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \
V(SLOPPY_FUNCTION_WITH_NAME_MAP_INDEX, Map, sloppy_function_with_name_map) \
V(SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
sloppy_function_without_prototype_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) \
V(STRICT_FUNCTION_WITH_NAME_MAP_INDEX, Map, strict_function_with_name_map) \
V(STRICT_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX, Map, \
strict_function_with_readonly_prototype_map) \
V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
strict_function_without_prototype_map) \
V(METHOD_WITH_NAME_MAP_INDEX, Map, method_with_name_map) \
V(METHOD_WITH_HOME_OBJECT_MAP_INDEX, Map, method_with_home_object_map) \
V(METHOD_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
method_with_name_and_home_object_map) \
V(ASYNC_FUNCTION_MAP_INDEX, Map, async_function_map) \
V(ASYNC_FUNCTION_WITH_NAME_MAP_INDEX, Map, async_function_with_name_map) \
V(ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX, Map, \
async_function_with_home_object_map) \
V(ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
async_function_with_name_and_home_object_map) \
V(GENERATOR_FUNCTION_MAP_INDEX, Map, generator_function_map) \
V(GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX, Map, \
generator_function_with_name_map) \
V(GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX, Map, \
generator_function_with_home_object_map) \
V(GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
generator_function_with_name_and_home_object_map) \
[async-iteration] implement AsyncGenerator - Introduce new struct AsyncGeneratorRequest, which holds information pertinent to resuming execution of an AsyncGenerator, such as the Promise associated with the async generator request. It is intended to be used as a singly linked list, and holds a pointer to the next item in te queue. - Introduce JSAsyncGeneratorObject (subclass of JSGeneratorObject), which includes several new internal fields (`queue` which contains a singly linked list of AsyncGeneratorRequest objects, and `await_input` which contains the sent value from an Await expression (This is necessary to prevent function.sent (used by yield*) from having the sent value observably overwritten during execution). - Modify SuspendGenerator to accept a set of Flags, which indicate whether the suspend is for a Yield or Await, and whether it takes place on an async generator or ES6 generator. - Introduce interpreter intrinsics and TF intrinsic lowering for accessing the await input of an async generator - Modify the JSGeneratorStore operator to understand whether or not it's suspending for a normal yield, or an AsyncGenerator Await. This ensures appropriate registers are stored. - Add versions of ResumeGeneratorTrampoline which store the input value in a different field depending on wether it's an AsyncGenerator Await resume, or an ordinary resume. Also modifies whether debug code will assert that the generator object is a JSGeneratorObject or a JSAsyncGeneratorObject depending on the resume type. BUG=v8:5855 R=bmeurer@chromium.org, rmcilroy@chromium.org, jgruber@chromium.org, littledan@chromium.org, neis@chromium.org TBR=marja@chromium.org Change-Id: I9d58df1d344465fc937fe7eed322424204497187 Reviewed-on: https://chromium-review.googlesource.com/446961 Commit-Queue: Caitlin Potter <caitp@igalia.com> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Hannes Payer <hpayer@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#44240}
2017-03-29 13:41:45 +00:00
V(ASYNC_GENERATOR_FUNCTION_MAP_INDEX, Map, async_generator_function_map) \
V(ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX, Map, \
async_generator_function_with_name_map) \
V(ASYNC_GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX, Map, \
async_generator_function_with_home_object_map) \
V(ASYNC_GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX, Map, \
async_generator_function_with_name_and_home_object_map) \
V(CLASS_FUNCTION_MAP_INDEX, Map, class_function_map) \
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(NATIVE_FUNCTION_MAP_INDEX, Map, native_function_map) \
V(WASM_EXCEPTION_CONSTRUCTOR_INDEX, JSFunction, wasm_exception_constructor) \
V(WASM_GLOBAL_CONSTRUCTOR_INDEX, JSFunction, wasm_global_constructor) \
V(WASM_INSTANCE_CONSTRUCTOR_INDEX, JSFunction, wasm_instance_constructor) \
V(WASM_MEMORY_CONSTRUCTOR_INDEX, JSFunction, wasm_memory_constructor) \
V(WASM_MODULE_CONSTRUCTOR_INDEX, JSFunction, wasm_module_constructor) \
V(WASM_TABLE_CONSTRUCTOR_INDEX, JSFunction, wasm_table_constructor) \
V(TYPED_ARRAY_FUN_INDEX, JSFunction, typed_array_function) \
V(TYPED_ARRAY_PROTOTYPE_INDEX, JSObject, typed_array_prototype) \
V(UINT16_ARRAY_FUN_INDEX, JSFunction, uint16_array_fun) \
V(UINT32_ARRAY_FUN_INDEX, JSFunction, uint32_array_fun) \
V(UINT8_ARRAY_FUN_INDEX, JSFunction, uint8_array_fun) \
V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \
NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
[es2015] Refactor the JSArrayIterator. This changes the JSArrayIterator to always have only a single instance type, instead of the zoo of instance types that we had before, and which became less useful with the specification update to when "next" is loaded from the iterator now. This greatly simplifies the baseline implementation of the array iterator, which now only looks at the iterated object during %ArrayIteratorPrototype%.next invocations. In TurboFan we introduce a new JSCreateArrayIterator operator, that holds the IterationKind and get's the iterated object as input. When optimizing %ArrayIteratorPrototype%.next in the JSCallReducer, we check whether the receiver is a JSCreateArrayIterator, and if so, we try to infer maps for the iterated object from there. If we find any, we speculatively assume that these won't have changed during iteration (as we did before with the previous approach), and generate fast code for both JSArray and JSTypedArray iteration. Drive-by-fix: Drop the fast_array_iteration protector, it's not necessary anymore since we have the deoptimization guard bit in the JSCallReducer now. This addresses the performance cliff noticed in webpack 4. The minimal repro on the tracking bug goes from console.timeEnd: mono, 124.773000 console.timeEnd: poly, 670.353000 to console.timeEnd: mono, 118.709000 console.timeEnd: poly, 141.393000 so that's a 4.7x improvement. Also make presubmit happy by adding the missing #undef's. Bug: v8:7510, v7:7514 Change-Id: I79a46bfa2cd0f0710e09365ef72519b1bbb667b5 Reviewed-on: https://chromium-review.googlesource.com/946098 Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#51725}
2018-03-02 19:31:01 +00:00
NATIVE_CONTEXT_IMPORTED_FIELDS(V)
// A table of all script contexts. Every loaded top-level script with top-level
// lexical declarations contributes its ScriptContext into this table.
//
// The table is a fixed array, its first slot is the current used count and
// the subsequent slots 1..used contain ScriptContexts.
class ScriptContextTable : public FixedArray {
public:
DECL_CAST2(ScriptContextTable)
struct LookupResult {
int context_index;
int slot_index;
VariableMode mode;
InitializationFlag init_flag;
MaybeAssignedFlag maybe_assigned_flag;
};
inline int used() const;
inline void set_used(int used);
static inline Handle<Context> GetContext(Isolate* isolate,
Handle<ScriptContextTable> table,
int i);
// Lookup a variable `name` in a ScriptContextTable.
// If it returns true, the variable is found and `result` contains
// valid information about its location.
// If it returns false, `result` is untouched.
V8_WARN_UNUSED_RESULT
static bool Lookup(Isolate* isolate, Handle<ScriptContextTable> table,
Handle<String> name, LookupResult* result);
V8_WARN_UNUSED_RESULT
static Handle<ScriptContextTable> Extend(Handle<ScriptContextTable> table,
Handle<Context> script_context);
static const int kUsedSlotIndex = 0;
static const int kFirstContextSlotIndex = 1;
static const int kMinLength = kFirstContextSlotIndex;
OBJECT_CONSTRUCTORS(ScriptContextTable, FixedArray);
};
// 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:
//
// [ scope_info ] This is the scope info describing the current context. It
// contains the names of statically allocated context slots,
// and stack-allocated locals. The names are needed for
// dynamic lookups in the presence of 'with' or 'eval', and
// for the debugger.
//
// [ previous ] A pointer to the previous context.
//
// [ extension ] Additional data.
//
// For native contexts, it contains the global object.
// For module contexts, it contains the module object.
// For await contexts, it contains the generator object.
// For block contexts, it may contain an "extension object".
// For with contexts, it contains an "extension object".
//
// An "extension object" is used to dynamically extend a
// context with additional variables, namely in the
// implementation of the 'with' construct and the 'eval'
// construct. For instance, Context::Lookup also searches
// the extension object for properties. (Storing the
// extension object is the original purpose of this context
// slot, hence the name.)
//
// [ native_context ] A pointer to the native context.
//
// 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).
// The native context contains additional slots for fast access to native
// properties.
//
// Finally, with Harmony scoping, the JSFunction representing a top level
// script will have the ScriptContext rather than a FunctionContext.
// Script contexts from all top-level scripts are gathered in
// ScriptContextTable.
class Context : public HeapObjectPtr {
public:
NEVER_READ_ONLY_SPACE
DECL_CAST2(Context)
// [length]: length of the context.
V8_INLINE int length() const;
V8_INLINE void set_length(int value);
// Setter and getter for elements.
V8_INLINE Object* get(int index) const;
V8_INLINE void set(int index, Object* value);
// Setter with explicit barrier mode.
V8_INLINE void set(int index, Object* value, WriteBarrierMode mode);
// Layout description.
#define CONTEXT_FIELDS(V) \
V(kLengthOffset, kTaggedSize) \
/* TODO(ishell): remove this fixedArray-like header size. */ \
V(kHeaderSize, 0) \
V(kStartOfTaggedFieldsOffset, 0) \
V(kStartOfStrongFieldsOffset, 0) \
/* Tagged fields. */ \
V(kScopeInfoOffset, kTaggedSize) \
V(kPreviousOffset, kTaggedSize) \
V(kExtensionOffset, kTaggedSize) \
V(kNativeContextOffset, kTaggedSize) \
/* Header size. */ \
/* TODO(ishell): use this as header size once MIN_CONTEXT_SLOTS */ \
/* is removed in favour of offset-based access to common fields. */ \
V(kTodoHeaderSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, CONTEXT_FIELDS)
#undef CONTEXT_FIELDS
// Garbage collection support.
V8_INLINE static constexpr int SizeFor(int length) {
// TODO(ishell): switch to kTodoHeaderSize based approach once we no longer
// reference common Context fields via index
return kHeaderSize + length * kTaggedSize;
}
// Code Generation support.
// Offset of the element from the beginning of object.
V8_INLINE static constexpr int OffsetOfElementAt(int index) {
return SizeFor(index);
}
// Offset of the element from the heap object pointer.
V8_INLINE static constexpr int SlotOffset(int index) {
return SizeFor(index) - kHeapObjectTag;
}
// TODO(ishell): eventually migrate to the offset based access instead of
// index-based.
// The default context slot layout; indices are FixedArray slot indices.
enum Field {
// TODO(shell): use offset-based approach for accessing common values.
// These slots are in all contexts.
SCOPE_INFO_INDEX,
PREVIOUS_INDEX,
EXTENSION_INDEX,
NATIVE_CONTEXT_INDEX,
// These slots are only in native contexts.
#define NATIVE_CONTEXT_SLOT(index, type, name) index,
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_SLOT)
#undef NATIVE_CONTEXT_SLOT
// Properties from here are treated as weak references by the full GC.
// Scavenge treats them as strong references.
OPTIMIZED_CODE_LIST, // Weak.
DEOPTIMIZED_CODE_LIST, // Weak.
NEXT_CONTEXT_LINK, // Weak.
// Total number of slots.
NATIVE_CONTEXT_SLOTS,
FIRST_WEAK_SLOT = OPTIMIZED_CODE_LIST,
FIRST_JS_ARRAY_MAP_SLOT = JS_ARRAY_PACKED_SMI_ELEMENTS_MAP_INDEX,
// TODO(shell): Remove, once it becomes zero
MIN_CONTEXT_SLOTS = GLOBAL_PROXY_INDEX,
// This slot holds the thrown value in catch contexts.
THROWN_OBJECT_INDEX = MIN_CONTEXT_SLOTS,
// These slots hold values in debug evaluate contexts.
WRAPPED_CONTEXT_INDEX = MIN_CONTEXT_SLOTS,
WHITE_LIST_INDEX = MIN_CONTEXT_SLOTS + 1
};
// A region of native context entries containing maps for functions created
// by Builtins::kFastNewClosure.
static const int FIRST_FUNCTION_MAP_INDEX = SLOPPY_FUNCTION_MAP_INDEX;
static const int LAST_FUNCTION_MAP_INDEX = CLASS_FUNCTION_MAP_INDEX;
static const int kNoContext = 0;
static const int kInvalidContext = 1;
void ResetErrorsThrown();
void IncrementErrorsThrown();
int GetErrorsThrown();
// Direct slot access.
inline void set_scope_info(ScopeInfo scope_info);
inline Context previous();
inline void set_previous(Context context);
inline Object* next_context_link();
inline bool has_extension();
inline HeapObject* extension();
inline void set_extension(HeapObject* object);
[es6] Parameter scopes for sloppy eval This CL is a nightmare! For the utterly irrelevant edge case of a sloppy function with non-simple parameters and a call to direct eval, like here, let x = 1;   function f(g = () => x) {     var y     eval("var x = 2")     return g() + x // f() = 3   } we have to do all of the following, on top of the declaration block ("varblock") contexts we already introduce around the body: - Introduce the ability for varblock contexts to have both a ScopeInfo and an extension object (e.g., the body varblock in the example will contain both a static var y and a dynamic var x). No other scope needs that. Since there are no context slots left, a special new struct is introduced that pairs up scope info and extension object. - When declaring lookup slots in the runtime, this new struct is allocated in the case where an extension object has to be added to a block scope (at which point the block's extension slot still contains a plain ScopeInfo). - While at it, introduce some abstraction to access context extension slots in a more controlled manner, in order to keep special-casing to a minimum. - Make sure that even empty varblock contexts do not get optimised away when they contain a sloppy eval, so that they can host the potential extension object. - Extend dynamic search for declaration contexts (used by sloppy direct eval) to recognize varblock contexts. - In the parser, if a function has a sloppy direct eval, introduce an additional varblock scope around each non-simple (desugared) parameter, as required by the spec to contain possible dynamic var bindings. - In the pattern rewriter, add the ability to hoist the named variables the pattern declares to an outer scope. That is required because the actual destructuring has to be evaluated inside the protecting varblock scope, but the bindings that the desugaring introduces are in the outer scope. - ScopeInfos need to save the information whether a block is a varblock, to make sloppy eval calls work correctly that deserialise them as part of the scope chain. - Add the ability to materialize block scopes with extension objects in the debugger. Likewise, enable setting extension variables in block scopes via the debugger interface. - While at it, refactor and unify some respective code in the debugger. Sorry, this CL is large. I could try to split it up, but everything is rather entangled. @mstarzinger: Please review the changes to contexts. @yangguo: Please have a look at the debugger stuff. R=littledan@chromium.org, mstarzinger@chromium.org, yangguo@chromium.org BUG=v8:811,v8:2160 LOG=N Review URL: https://codereview.chromium.org/1292753007 Cr-Commit-Position: refs/heads/master@{#30295}
2015-08-21 10:58:35 +00:00
JSObject* extension_object();
JSReceiver* extension_receiver();
ScopeInfo scope_info();
// Find the module context (assuming there is one) and return the associated
// module object.
Module* module();
// Get the context where var declarations will be hoisted to, which
// may be the context itself.
Context declaration_context();
[es6] Parameter scopes for sloppy eval This CL is a nightmare! For the utterly irrelevant edge case of a sloppy function with non-simple parameters and a call to direct eval, like here, let x = 1;   function f(g = () => x) {     var y     eval("var x = 2")     return g() + x // f() = 3   } we have to do all of the following, on top of the declaration block ("varblock") contexts we already introduce around the body: - Introduce the ability for varblock contexts to have both a ScopeInfo and an extension object (e.g., the body varblock in the example will contain both a static var y and a dynamic var x). No other scope needs that. Since there are no context slots left, a special new struct is introduced that pairs up scope info and extension object. - When declaring lookup slots in the runtime, this new struct is allocated in the case where an extension object has to be added to a block scope (at which point the block's extension slot still contains a plain ScopeInfo). - While at it, introduce some abstraction to access context extension slots in a more controlled manner, in order to keep special-casing to a minimum. - Make sure that even empty varblock contexts do not get optimised away when they contain a sloppy eval, so that they can host the potential extension object. - Extend dynamic search for declaration contexts (used by sloppy direct eval) to recognize varblock contexts. - In the parser, if a function has a sloppy direct eval, introduce an additional varblock scope around each non-simple (desugared) parameter, as required by the spec to contain possible dynamic var bindings. - In the pattern rewriter, add the ability to hoist the named variables the pattern declares to an outer scope. That is required because the actual destructuring has to be evaluated inside the protecting varblock scope, but the bindings that the desugaring introduces are in the outer scope. - ScopeInfos need to save the information whether a block is a varblock, to make sloppy eval calls work correctly that deserialise them as part of the scope chain. - Add the ability to materialize block scopes with extension objects in the debugger. Likewise, enable setting extension variables in block scopes via the debugger interface. - While at it, refactor and unify some respective code in the debugger. Sorry, this CL is large. I could try to split it up, but everything is rather entangled. @mstarzinger: Please review the changes to contexts. @yangguo: Please have a look at the debugger stuff. R=littledan@chromium.org, mstarzinger@chromium.org, yangguo@chromium.org BUG=v8:811,v8:2160 LOG=N Review URL: https://codereview.chromium.org/1292753007 Cr-Commit-Position: refs/heads/master@{#30295}
2015-08-21 10:58:35 +00:00
bool is_declaration_context();
// Get the next closure's context on the context chain.
Context closure_context();
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.
JSGlobalProxy* global_proxy();
void set_global_proxy(JSGlobalProxy* global);
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
// Get the JSGlobalObject object.
V8_EXPORT_PRIVATE JSGlobalObject* global_object();
// 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
// Compute the native context.
inline NativeContext native_context() const;
inline void set_native_context(NativeContext context);
// Predicates for context types. IsNativeContext is already defined on
// Object.
inline bool IsFunctionContext() const;
inline bool IsCatchContext() const;
inline bool IsWithContext() const;
inline bool IsDebugEvaluateContext() const;
2018-09-27 20:11:42 +00:00
inline bool IsAwaitContext() const;
inline bool IsBlockContext() const;
inline bool IsModuleContext() const;
inline bool IsEvalContext() const;
inline bool IsScriptContext() const;
inline bool HasSameSecurityTokenAs(Context that) const;
// 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();
Handle<Object> ErrorMessageForCodeGenerationFromStrings();
static int ImportedFieldIndexForName(Handle<String> name);
static int IntrinsicIndexForName(Handle<String> name);
static int IntrinsicIndexForName(const unsigned char* name, int length);
#define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
inline void set_##name(type##ArgType value); \
inline bool is_##name(type##ArgType value) const; \
inline type##ArgType name() const;
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
#undef NATIVE_CONTEXT_FIELD_ACCESSORS
// Lookup the slot called name, starting with the current context.
// There are three possibilities:
//
// 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).
//
// 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.
//
// 3) result->IsModule():
// The binding was found in module imports or exports.
// *attributes is never ABSENT. imports are READ_ONLY.
//
// 4) result.is_null():
// There was no binding found, *index is always -1 and *attributes is
// always ABSENT.
Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags,
int* index, PropertyAttributes* attributes,
InitializationFlag* init_flag,
VariableMode* variable_mode,
bool* is_sloppy_function_name = nullptr);
static inline int FunctionMapIndex(LanguageMode language_mode,
FunctionKind kind, bool has_prototype_slot,
bool has_shared_name,
bool needs_home_object);
static int ArrayMapIndex(ElementsKind elements_kind) {
DCHECK(IsFastElementsKind(elements_kind));
return elements_kind + FIRST_JS_ARRAY_MAP_SLOT;
}
inline Map GetInitialJSArrayMap(ElementsKind kind) const;
static const int kNotFound = -1;
// Dispatched behavior.
DECL_PRINTER(Context)
DECL_VERIFIER(Context)
typedef FlexibleBodyDescriptor<kStartOfTaggedFieldsOffset> BodyDescriptor;
private:
#ifdef DEBUG
// Bootstrapping-aware type checks.
V8_EXPORT_PRIVATE static bool IsBootstrappingOrNativeContext(Isolate* isolate,
Object* object);
static bool IsBootstrappingOrValidParentContext(Object* object, Context kid);
#endif
OBJECT_CONSTRUCTORS(Context, HeapObjectPtr)
};
class NativeContext : public Context {
public:
DECL_CAST2(NativeContext)
// TODO(neis): Move some stuff from Context here.
// [microtask_queue]: pointer to the MicrotaskQueue object.
DECL_PRIMITIVE_ACCESSORS(microtask_queue, MicrotaskQueue*)
// Dispatched behavior.
DECL_PRINTER(NativeContext)
DECL_VERIFIER(NativeContext)
// Layout description.
#define NATIVE_CONTEXT_FIELDS_DEF(V) \
/* TODO(ishell): move definition of common context offsets to Context. */ \
V(kStartOfNativeContextFieldsOffset, \
(FIRST_WEAK_SLOT - MIN_CONTEXT_SLOTS) * kTaggedSize) \
V(kEndOfStrongFieldsOffset, 0) \
V(kStartOfWeakFieldsOffset, \
(NATIVE_CONTEXT_SLOTS - FIRST_WEAK_SLOT) * kTaggedSize) \
V(kEndOfWeakFieldsOffset, 0) \
V(kEndOfNativeContextFieldsOffset, 0) \
V(kEndOfTaggedFieldsOffset, 0) \
/* Raw data. */ \
V(kMicrotaskQueueOffset, kSystemPointerSize) \
/* Total size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(Context::kTodoHeaderSize,
NATIVE_CONTEXT_FIELDS_DEF)
#undef NATIVE_CONTEXT_FIELDS_DEF
class BodyDescriptor;
private:
STATIC_ASSERT(OffsetOfElementAt(EMBEDDER_DATA_INDEX) ==
Internals::kNativeContextEmbedderDataOffset);
OBJECT_CONSTRUCTORS(NativeContext, Context);
};
typedef Context::Field ContextField;
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_CONTEXTS_H_