[turbofan] Enforce native context specialization.
There were once plans to generate cross-context code with TurboFan, however that doesn't fit into the model anymore, and so all of this is essentially dead untested code (and thus most likely already broken in subtle ways). With this mode still in place it would also be a lot harder to make inlining based on SharedFunctionInfo work. BUG=v8:2206,v8:5499 R=jarin@chromium.org Review-Url: https://codereview.chromium.org/2406803002 Cr-Commit-Position: refs/heads/master@{#40109}
This commit is contained in:
parent
cc02e74320
commit
f6bd23f244
@ -43,15 +43,14 @@ class CompilationInfo final {
|
||||
kSerializing = 1 << 7,
|
||||
kFunctionContextSpecializing = 1 << 8,
|
||||
kFrameSpecializing = 1 << 9,
|
||||
kNativeContextSpecializing = 1 << 10,
|
||||
kInliningEnabled = 1 << 11,
|
||||
kDisableFutureOptimization = 1 << 12,
|
||||
kSplittingEnabled = 1 << 13,
|
||||
kDeoptimizationEnabled = 1 << 14,
|
||||
kSourcePositionsEnabled = 1 << 15,
|
||||
kBailoutOnUninitialized = 1 << 16,
|
||||
kOptimizeFromBytecode = 1 << 17,
|
||||
kTypeFeedbackEnabled = 1 << 18,
|
||||
kInliningEnabled = 1 << 10,
|
||||
kDisableFutureOptimization = 1 << 11,
|
||||
kSplittingEnabled = 1 << 12,
|
||||
kDeoptimizationEnabled = 1 << 13,
|
||||
kSourcePositionsEnabled = 1 << 14,
|
||||
kBailoutOnUninitialized = 1 << 15,
|
||||
kOptimizeFromBytecode = 1 << 16,
|
||||
kTypeFeedbackEnabled = 1 << 17,
|
||||
};
|
||||
|
||||
CompilationInfo(ParseInfo* parse_info, Handle<JSFunction> closure);
|
||||
@ -143,14 +142,6 @@ class CompilationInfo final {
|
||||
|
||||
bool is_frame_specializing() const { return GetFlag(kFrameSpecializing); }
|
||||
|
||||
void MarkAsNativeContextSpecializing() {
|
||||
SetFlag(kNativeContextSpecializing);
|
||||
}
|
||||
|
||||
bool is_native_context_specializing() const {
|
||||
return GetFlag(kNativeContextSpecializing);
|
||||
}
|
||||
|
||||
void MarkAsDeoptimizationEnabled() { SetFlag(kDeoptimizationEnabled); }
|
||||
|
||||
bool is_deoptimization_enabled() const {
|
||||
|
@ -194,7 +194,6 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
|
||||
CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
|
||||
Node* target = NodeProperties::GetValueInput(node, 0);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
|
||||
@ -298,19 +297,8 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
|
||||
Handle<Object> feedback(nexus.GetFeedback(), isolate());
|
||||
if (feedback->IsAllocationSite()) {
|
||||
// Retrieve the Array function from the {node}.
|
||||
Node* array_function;
|
||||
Handle<Context> native_context;
|
||||
if (GetNativeContext(node).ToHandle(&native_context)) {
|
||||
array_function = jsgraph()->HeapConstant(
|
||||
handle(native_context->array_function(), isolate()));
|
||||
} else {
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
array_function = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true),
|
||||
native_context, native_context, effect);
|
||||
}
|
||||
Node* array_function = jsgraph()->HeapConstant(
|
||||
handle(native_context()->array_function(), isolate()));
|
||||
|
||||
// Check that the {target} is still the {array_function}.
|
||||
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
|
||||
@ -353,7 +341,6 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
|
||||
int const arity = static_cast<int>(p.arity() - 2);
|
||||
Node* target = NodeProperties::GetValueInput(node, 0);
|
||||
Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
@ -413,19 +400,8 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
|
||||
Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
|
||||
|
||||
// Retrieve the Array function from the {node}.
|
||||
Node* array_function;
|
||||
Handle<Context> native_context;
|
||||
if (GetNativeContext(node).ToHandle(&native_context)) {
|
||||
array_function = jsgraph()->HeapConstant(
|
||||
handle(native_context->array_function(), isolate()));
|
||||
} else {
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
array_function = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true),
|
||||
native_context, native_context, effect);
|
||||
}
|
||||
Node* array_function = jsgraph()->HeapConstant(
|
||||
handle(native_context()->array_function(), isolate()));
|
||||
|
||||
// Check that the {target} is still the {array_function}.
|
||||
Node* check = graph()->NewNode(simplified()->ReferenceEqual(), target,
|
||||
@ -469,25 +445,14 @@ Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<Context> JSCallReducer::GetNativeContext(Node* node) {
|
||||
Node* const context = NodeProperties::GetContextInput(node);
|
||||
return NodeProperties::GetSpecializationNativeContext(context,
|
||||
native_context());
|
||||
}
|
||||
|
||||
|
||||
Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
|
||||
|
||||
|
||||
Isolate* JSCallReducer::isolate() const { return jsgraph()->isolate(); }
|
||||
|
||||
|
||||
CommonOperatorBuilder* JSCallReducer::common() const {
|
||||
return jsgraph()->common();
|
||||
}
|
||||
|
||||
|
||||
JSOperatorBuilder* JSCallReducer::javascript() const {
|
||||
return jsgraph()->javascript();
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ class JSCallReducer final : public AdvancedReducer {
|
||||
typedef base::Flags<Flag> Flags;
|
||||
|
||||
JSCallReducer(Editor* editor, JSGraph* jsgraph, Flags flags,
|
||||
MaybeHandle<Context> native_context)
|
||||
Handle<Context> native_context)
|
||||
: AdvancedReducer(editor),
|
||||
jsgraph_(jsgraph),
|
||||
flags_(flags),
|
||||
@ -47,20 +47,18 @@ class JSCallReducer final : public AdvancedReducer {
|
||||
Reduction ReduceJSCallConstruct(Node* node);
|
||||
Reduction ReduceJSCallFunction(Node* node);
|
||||
|
||||
MaybeHandle<Context> GetNativeContext(Node* node);
|
||||
|
||||
Graph* graph() const;
|
||||
Flags flags() const { return flags_; }
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
Isolate* isolate() const;
|
||||
MaybeHandle<Context> native_context() const { return native_context_; }
|
||||
Handle<Context> native_context() const { return native_context_; }
|
||||
CommonOperatorBuilder* common() const;
|
||||
JSOperatorBuilder* javascript() const;
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
|
||||
JSGraph* const jsgraph_;
|
||||
Flags const flags_;
|
||||
MaybeHandle<Context> const native_context_;
|
||||
Handle<Context> const native_context_;
|
||||
};
|
||||
|
||||
DEFINE_OPERATORS_FOR_FLAGS(JSCallReducer::Flags)
|
||||
|
@ -353,22 +353,18 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
Node* const elements = AllocateAliasedArguments(
|
||||
effect, control, args_state, context, shared, &has_aliased_arguments);
|
||||
effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
|
||||
// Load the arguments object map from the current native context.
|
||||
Node* const load_native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
Node* const load_arguments_map = effect = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForContextSlot(
|
||||
has_aliased_arguments ? Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX
|
||||
: Context::SLOPPY_ARGUMENTS_MAP_INDEX)),
|
||||
load_native_context, effect, control);
|
||||
// Load the arguments object map.
|
||||
Node* const arguments_map = jsgraph()->HeapConstant(handle(
|
||||
has_aliased_arguments ? native_context()->fast_aliased_arguments_map()
|
||||
: native_context()->sloppy_arguments_map(),
|
||||
isolate()));
|
||||
// Actually allocate and initialize the arguments object.
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
||||
int length = args_state_info.parameter_count() - 1; // Minus receiver.
|
||||
STATIC_ASSERT(JSSloppyArgumentsObject::kSize == 5 * kPointerSize);
|
||||
a.Allocate(JSSloppyArgumentsObject::kSize);
|
||||
a.Store(AccessBuilder::ForMap(), load_arguments_map);
|
||||
a.Store(AccessBuilder::ForMap(), arguments_map);
|
||||
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
|
||||
a.Store(AccessBuilder::ForJSObjectElements(), elements);
|
||||
a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
|
||||
@ -379,7 +375,6 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
} else if (type == CreateArgumentsType::kUnmappedArguments) {
|
||||
// Use inline allocation for all unmapped arguments objects within inlined
|
||||
// (i.e. non-outermost) frames, independent of the object size.
|
||||
Node* const context = NodeProperties::GetContextInput(node);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
// Choose the correct frame state and frame state info depending on
|
||||
// whether there conceptually is an arguments adaptor frame in the call
|
||||
@ -389,21 +384,16 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
// Prepare element backing store to be used by arguments object.
|
||||
Node* const elements = AllocateArguments(effect, control, args_state);
|
||||
effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
|
||||
// Load the arguments object map from the current native context.
|
||||
Node* const load_native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
Node* const load_arguments_map = effect = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForContextSlot(
|
||||
Context::STRICT_ARGUMENTS_MAP_INDEX)),
|
||||
load_native_context, effect, control);
|
||||
// Load the arguments object map.
|
||||
Node* const arguments_map = jsgraph()->HeapConstant(
|
||||
handle(native_context()->strict_arguments_map(), isolate()));
|
||||
// Actually allocate and initialize the arguments object.
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
||||
int length = args_state_info.parameter_count() - 1; // Minus receiver.
|
||||
STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize);
|
||||
a.Allocate(JSStrictArgumentsObject::kSize);
|
||||
a.Store(AccessBuilder::ForMap(), load_arguments_map);
|
||||
a.Store(AccessBuilder::ForMap(), arguments_map);
|
||||
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
|
||||
a.Store(AccessBuilder::ForJSObjectElements(), elements);
|
||||
a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length));
|
||||
@ -416,7 +406,6 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
int start_index = shared->internal_formal_parameter_count();
|
||||
// Use inline allocation for all unmapped arguments objects within inlined
|
||||
// (i.e. non-outermost) frames, independent of the object size.
|
||||
Node* const context = NodeProperties::GetContextInput(node);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
// Choose the correct frame state and frame state info depending on
|
||||
// whether there conceptually is an arguments adaptor frame in the call
|
||||
@ -427,14 +416,9 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
Node* const elements =
|
||||
AllocateRestArguments(effect, control, args_state, start_index);
|
||||
effect = elements->op()->EffectOutputCount() > 0 ? elements : effect;
|
||||
// Load the JSArray object map from the current native context.
|
||||
Node* const load_native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
Node* const load_jsarray_map = effect = graph()->NewNode(
|
||||
simplified()->LoadField(AccessBuilder::ForContextSlot(
|
||||
Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX)),
|
||||
load_native_context, effect, control);
|
||||
// Load the JSArray object map.
|
||||
Node* const jsarray_map = jsgraph()->HeapConstant(handle(
|
||||
native_context()->js_array_fast_elements_map_index(), isolate()));
|
||||
// Actually allocate and initialize the jsarray.
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
||||
@ -444,7 +428,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
|
||||
int length = std::max(0, argument_count - start_index);
|
||||
STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize);
|
||||
a.Allocate(JSArray::kSize);
|
||||
a.Store(AccessBuilder::ForMap(), load_jsarray_map);
|
||||
a.Store(AccessBuilder::ForMap(), jsarray_map);
|
||||
a.Store(AccessBuilder::ForJSObjectProperties(), properties);
|
||||
a.Store(AccessBuilder::ForJSObjectElements(), elements);
|
||||
a.Store(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS),
|
||||
@ -462,7 +446,6 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
|
||||
int capacity,
|
||||
Handle<AllocationSite> site) {
|
||||
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
@ -478,13 +461,10 @@ Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
|
||||
dependencies()->AssumeTenuringDecision(site);
|
||||
dependencies()->AssumeTransitionStable(site);
|
||||
|
||||
// Retrieve the initial map for the array from the appropriate native context.
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
Node* js_array_map = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::ArrayMapIndex(elements_kind), true),
|
||||
native_context, native_context, effect);
|
||||
// Retrieve the initial map for the array.
|
||||
int const array_map_index = Context::ArrayMapIndex(elements_kind);
|
||||
Node* js_array_map = jsgraph()->HeapConstant(
|
||||
handle(Map::cast(native_context()->get(array_map_index)), isolate()));
|
||||
|
||||
// Setup elements and properties.
|
||||
Node* elements;
|
||||
@ -684,14 +664,10 @@ Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
int function_map_index =
|
||||
int const function_map_index =
|
||||
Context::FunctionMapIndex(shared->language_mode(), shared->kind());
|
||||
Node* function_map = effect =
|
||||
graph()->NewNode(javascript()->LoadContext(0, function_map_index, true),
|
||||
native_context, native_context, effect);
|
||||
Node* function_map = jsgraph()->HeapConstant(
|
||||
handle(Map::cast(native_context()->get(function_map_index)), isolate()));
|
||||
// Note that it is only safe to embed the raw entry point of the compile
|
||||
// lazy stub into the code, because that stub is immortal and immovable.
|
||||
Node* compile_entry = jsgraph()->IntPtrConstant(reinterpret_cast<intptr_t>(
|
||||
@ -723,23 +699,8 @@ Reduction JSCreateLowering::ReduceJSCreateIterResultObject(Node* node) {
|
||||
Node* done = NodeProperties::GetValueInput(node, 1);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
|
||||
Node* iterator_result_map;
|
||||
Handle<Context> native_context;
|
||||
if (GetSpecializationNativeContext(node).ToHandle(&native_context)) {
|
||||
// Specialize to the constant JSIteratorResult map to enable map check
|
||||
// elimination to eliminate subsequent checks in case of inlining.
|
||||
iterator_result_map = jsgraph()->HeapConstant(
|
||||
handle(native_context->iterator_result_map(), isolate()));
|
||||
} else {
|
||||
// Load the JSIteratorResult map for the {context}.
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
iterator_result_map = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::ITERATOR_RESULT_MAP_INDEX, true),
|
||||
native_context, native_context, effect);
|
||||
}
|
||||
Node* iterator_result_map = jsgraph()->HeapConstant(
|
||||
handle(native_context()->iterator_result_map(), isolate()));
|
||||
|
||||
// Emit code to allocate the JSIteratorResult instance.
|
||||
AllocationBuilder a(jsgraph(), effect, graph()->start());
|
||||
@ -798,9 +759,6 @@ Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* extension = jsgraph()->TheHoleConstant();
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
|
||||
int context_length = slot_count + Context::MIN_CONTEXT_SLOTS;
|
||||
@ -809,7 +767,7 @@ Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
|
||||
native_context);
|
||||
jsgraph()->HeapConstant(native_context()));
|
||||
for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
|
||||
a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
|
||||
}
|
||||
@ -829,9 +787,6 @@ Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
|
||||
AllocationBuilder aa(jsgraph(), effect, control);
|
||||
aa.Allocate(ContextExtension::kSize);
|
||||
@ -847,7 +802,7 @@ Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
|
||||
native_context);
|
||||
jsgraph()->HeapConstant(native_context()));
|
||||
RelaxControls(node);
|
||||
a.FinishAndChange(node);
|
||||
return Changed(node);
|
||||
@ -862,9 +817,6 @@ Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
|
||||
AllocationBuilder aa(jsgraph(), effect, control);
|
||||
aa.Allocate(ContextExtension::kSize);
|
||||
@ -883,7 +835,7 @@ Reduction JSCreateLowering::ReduceJSCreateCatchContext(Node* node) {
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
|
||||
native_context);
|
||||
jsgraph()->HeapConstant(native_context()));
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX),
|
||||
exception);
|
||||
RelaxControls(node);
|
||||
@ -904,9 +856,7 @@ Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* extension = jsgraph()->Constant(scope_info);
|
||||
Node* native_context = effect = graph()->NewNode(
|
||||
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
|
||||
context, context, effect);
|
||||
|
||||
AllocationBuilder a(jsgraph(), effect, control);
|
||||
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
|
||||
a.AllocateArray(context_length, factory()->block_context_map());
|
||||
@ -914,7 +864,7 @@ Reduction JSCreateLowering::ReduceJSCreateBlockContext(Node* node) {
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
|
||||
a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
|
||||
native_context);
|
||||
jsgraph()->HeapConstant(native_context()));
|
||||
for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) {
|
||||
a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant());
|
||||
}
|
||||
@ -1279,13 +1229,6 @@ MaybeHandle<LiteralsArray> JSCreateLowering::GetSpecializationLiterals(
|
||||
return MaybeHandle<LiteralsArray>();
|
||||
}
|
||||
|
||||
MaybeHandle<Context> JSCreateLowering::GetSpecializationNativeContext(
|
||||
Node* node) {
|
||||
Node* const context = NodeProperties::GetContextInput(node);
|
||||
return NodeProperties::GetSpecializationNativeContext(context,
|
||||
native_context_);
|
||||
}
|
||||
|
||||
Factory* JSCreateLowering::factory() const { return isolate()->factory(); }
|
||||
|
||||
Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }
|
||||
|
@ -31,7 +31,7 @@ class JSCreateLowering final : public AdvancedReducer {
|
||||
public:
|
||||
JSCreateLowering(Editor* editor, CompilationDependencies* dependencies,
|
||||
JSGraph* jsgraph, MaybeHandle<LiteralsArray> literals_array,
|
||||
MaybeHandle<Context> native_context, Zone* zone)
|
||||
Handle<Context> native_context, Zone* zone)
|
||||
: AdvancedReducer(editor),
|
||||
dependencies_(dependencies),
|
||||
jsgraph_(jsgraph),
|
||||
@ -77,13 +77,12 @@ class JSCreateLowering final : public AdvancedReducer {
|
||||
|
||||
// Infers the LiteralsArray to use for a given {node}.
|
||||
MaybeHandle<LiteralsArray> GetSpecializationLiterals(Node* node);
|
||||
// Infers the native context to use for a given {node}.
|
||||
MaybeHandle<Context> GetSpecializationNativeContext(Node* node);
|
||||
|
||||
Factory* factory() const;
|
||||
Graph* graph() const;
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
Isolate* isolate() const;
|
||||
Handle<Context> native_context() const { return native_context_; }
|
||||
JSOperatorBuilder* javascript() const;
|
||||
CommonOperatorBuilder* common() const;
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
@ -94,7 +93,7 @@ class JSCreateLowering final : public AdvancedReducer {
|
||||
CompilationDependencies* const dependencies_;
|
||||
JSGraph* const jsgraph_;
|
||||
MaybeHandle<LiteralsArray> const literals_array_;
|
||||
MaybeHandle<Context> const native_context_;
|
||||
Handle<Context> const native_context_;
|
||||
Zone* const zone_;
|
||||
};
|
||||
|
||||
|
@ -25,17 +25,15 @@ struct JSGlobalObjectSpecialization::ScriptContextTableLookupResult {
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
JSGlobalObjectSpecialization::JSGlobalObjectSpecialization(
|
||||
Editor* editor, JSGraph* jsgraph,
|
||||
MaybeHandle<Context> native_context, CompilationDependencies* dependencies)
|
||||
Editor* editor, JSGraph* jsgraph, Handle<JSGlobalObject> global_object,
|
||||
CompilationDependencies* dependencies)
|
||||
: AdvancedReducer(editor),
|
||||
jsgraph_(jsgraph),
|
||||
native_context_(native_context),
|
||||
global_object_(global_object),
|
||||
dependencies_(dependencies),
|
||||
type_cache_(TypeCache::Get()) {}
|
||||
|
||||
|
||||
Reduction JSGlobalObjectSpecialization::Reduce(Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kJSLoadGlobal:
|
||||
@ -71,13 +69,9 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
// Retrieve the global object from the given {node}.
|
||||
Handle<JSGlobalObject> global_object;
|
||||
if (!GetGlobalObject(node).ToHandle(&global_object)) return NoChange();
|
||||
|
||||
// Try to lookup the name on the script context table first (lexical scoping).
|
||||
ScriptContextTableLookupResult result;
|
||||
if (LookupInScriptContextTable(global_object, name, &result)) {
|
||||
if (LookupInScriptContextTable(name, &result)) {
|
||||
if (result.context->is_the_hole(result.index)) return NoChange();
|
||||
Node* context = jsgraph()->HeapConstant(result.context);
|
||||
Node* value = effect = graph()->NewNode(
|
||||
@ -89,7 +83,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) {
|
||||
|
||||
// Lookup on the global object instead. We only deal with own data
|
||||
// properties of the global object here (represented as PropertyCell).
|
||||
LookupIterator it(global_object, name, LookupIterator::OWN);
|
||||
LookupIterator it(global_object(), name, LookupIterator::OWN);
|
||||
if (it.state() != LookupIterator::DATA) return NoChange();
|
||||
if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
|
||||
Handle<PropertyCell> property_cell = it.GetPropertyCell();
|
||||
@ -158,13 +152,9 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
// Retrieve the global object from the given {node}.
|
||||
Handle<JSGlobalObject> global_object;
|
||||
if (!GetGlobalObject(node).ToHandle(&global_object)) return NoChange();
|
||||
|
||||
// Try to lookup the name on the script context table first (lexical scoping).
|
||||
ScriptContextTableLookupResult result;
|
||||
if (LookupInScriptContextTable(global_object, name, &result)) {
|
||||
if (LookupInScriptContextTable(name, &result)) {
|
||||
if (result.context->is_the_hole(result.index)) return NoChange();
|
||||
if (result.immutable) return NoChange();
|
||||
Node* context = jsgraph()->HeapConstant(result.context);
|
||||
@ -176,7 +166,7 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
|
||||
// Lookup on the global object instead. We only deal with own data
|
||||
// properties of the global object here (represented as PropertyCell).
|
||||
LookupIterator it(global_object, name, LookupIterator::OWN);
|
||||
LookupIterator it(global_object(), name, LookupIterator::OWN);
|
||||
if (it.state() != LookupIterator::DATA) return NoChange();
|
||||
if (!it.GetHolder<JSObject>()->IsJSGlobalObject()) return NoChange();
|
||||
Handle<PropertyCell> property_cell = it.GetPropertyCell();
|
||||
@ -251,21 +241,11 @@ Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) {
|
||||
return Replace(value);
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<JSGlobalObject> JSGlobalObjectSpecialization::GetGlobalObject(
|
||||
Node* node) {
|
||||
Node* const context = NodeProperties::GetContextInput(node);
|
||||
return NodeProperties::GetSpecializationGlobalObject(context,
|
||||
native_context());
|
||||
}
|
||||
|
||||
|
||||
bool JSGlobalObjectSpecialization::LookupInScriptContextTable(
|
||||
Handle<JSGlobalObject> global_object, Handle<Name> name,
|
||||
ScriptContextTableLookupResult* result) {
|
||||
Handle<Name> name, ScriptContextTableLookupResult* result) {
|
||||
if (!name->IsString()) return false;
|
||||
Handle<ScriptContextTable> script_context_table(
|
||||
global_object->native_context()->script_context_table(), isolate());
|
||||
global_object()->native_context()->script_context_table(), isolate());
|
||||
ScriptContextTable::LookupResult lookup_result;
|
||||
if (!ScriptContextTable::Lookup(script_context_table,
|
||||
Handle<String>::cast(name), &lookup_result)) {
|
||||
@ -279,27 +259,22 @@ bool JSGlobalObjectSpecialization::LookupInScriptContextTable(
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Graph* JSGlobalObjectSpecialization::graph() const {
|
||||
return jsgraph()->graph();
|
||||
}
|
||||
|
||||
|
||||
Isolate* JSGlobalObjectSpecialization::isolate() const {
|
||||
return jsgraph()->isolate();
|
||||
}
|
||||
|
||||
|
||||
CommonOperatorBuilder* JSGlobalObjectSpecialization::common() const {
|
||||
return jsgraph()->common();
|
||||
}
|
||||
|
||||
|
||||
JSOperatorBuilder* JSGlobalObjectSpecialization::javascript() const {
|
||||
return jsgraph()->javascript();
|
||||
}
|
||||
|
||||
|
||||
SimplifiedOperatorBuilder* JSGlobalObjectSpecialization::simplified() const {
|
||||
return jsgraph()->simplified();
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class TypeCache;
|
||||
class JSGlobalObjectSpecialization final : public AdvancedReducer {
|
||||
public:
|
||||
JSGlobalObjectSpecialization(Editor* editor, JSGraph* jsgraph,
|
||||
MaybeHandle<Context> native_context,
|
||||
Handle<JSGlobalObject> global_object,
|
||||
CompilationDependencies* dependencies);
|
||||
|
||||
Reduction Reduce(Node* node) final;
|
||||
@ -37,12 +37,8 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer {
|
||||
Reduction ReduceJSLoadGlobal(Node* node);
|
||||
Reduction ReduceJSStoreGlobal(Node* node);
|
||||
|
||||
// Retrieve the global object from the given {node} if known.
|
||||
MaybeHandle<JSGlobalObject> GetGlobalObject(Node* node);
|
||||
|
||||
struct ScriptContextTableLookupResult;
|
||||
bool LookupInScriptContextTable(Handle<JSGlobalObject> global_object,
|
||||
Handle<Name> name,
|
||||
bool LookupInScriptContextTable(Handle<Name> name,
|
||||
ScriptContextTableLookupResult* result);
|
||||
|
||||
Graph* graph() const;
|
||||
@ -51,11 +47,11 @@ class JSGlobalObjectSpecialization final : public AdvancedReducer {
|
||||
CommonOperatorBuilder* common() const;
|
||||
JSOperatorBuilder* javascript() const;
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
MaybeHandle<Context> native_context() const { return native_context_; }
|
||||
Handle<JSGlobalObject> global_object() const { return global_object_; }
|
||||
CompilationDependencies* dependencies() const { return dependencies_; }
|
||||
|
||||
JSGraph* const jsgraph_;
|
||||
MaybeHandle<Context> native_context_;
|
||||
Handle<JSGlobalObject> const global_object_;
|
||||
CompilationDependencies* const dependencies_;
|
||||
TypeCache const& type_cache_;
|
||||
|
||||
|
@ -57,7 +57,7 @@ bool HasOnlyStringMaps(T const& maps) {
|
||||
|
||||
JSNativeContextSpecialization::JSNativeContextSpecialization(
|
||||
Editor* editor, JSGraph* jsgraph, Flags flags,
|
||||
MaybeHandle<Context> native_context, CompilationDependencies* dependencies,
|
||||
Handle<Context> native_context, CompilationDependencies* dependencies,
|
||||
Zone* zone)
|
||||
: AdvancedReducer(editor),
|
||||
jsgraph_(jsgraph),
|
||||
@ -67,7 +67,6 @@ JSNativeContextSpecialization::JSNativeContextSpecialization(
|
||||
zone_(zone),
|
||||
type_cache_(TypeCache::Get()) {}
|
||||
|
||||
|
||||
Reduction JSNativeContextSpecialization::Reduce(Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kJSLoadContext:
|
||||
@ -89,13 +88,11 @@ Reduction JSNativeContextSpecialization::Reduce(Node* node) {
|
||||
Reduction JSNativeContextSpecialization::ReduceJSLoadContext(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
|
||||
ContextAccess const& access = ContextAccessOf(node->op());
|
||||
Handle<Context> native_context;
|
||||
// Specialize JSLoadContext(NATIVE_CONTEXT_INDEX) to the known native
|
||||
// context (if any), so we can constant-fold those fields, which is
|
||||
// safe, since the NATIVE_CONTEXT_INDEX slot is always immutable.
|
||||
if (access.index() == Context::NATIVE_CONTEXT_INDEX &&
|
||||
GetNativeContext(node).ToHandle(&native_context)) {
|
||||
Node* value = jsgraph()->HeapConstant(native_context);
|
||||
if (access.index() == Context::NATIVE_CONTEXT_INDEX) {
|
||||
Node* value = jsgraph()->HeapConstant(native_context());
|
||||
ReplaceWithValue(node, value);
|
||||
return Replace(value);
|
||||
}
|
||||
@ -120,12 +117,8 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
// Not much we can do if deoptimization support is disabled.
|
||||
if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
||||
|
||||
// Retrieve the native context from the given {node}.
|
||||
Handle<Context> native_context;
|
||||
if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange();
|
||||
|
||||
// Compute property access infos for the receiver maps.
|
||||
AccessInfoFactory access_info_factory(dependencies(), native_context,
|
||||
AccessInfoFactory access_info_factory(dependencies(), native_context(),
|
||||
graph()->zone());
|
||||
ZoneVector<PropertyAccessInfo> access_infos(zone());
|
||||
if (!access_info_factory.ComputePropertyAccessInfos(
|
||||
@ -174,9 +167,9 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
}
|
||||
|
||||
// Generate the actual property access.
|
||||
ValueEffectControl continuation = BuildPropertyAccess(
|
||||
receiver, value, context, frame_state_lazy, effect, control, name,
|
||||
native_context, access_info, access_mode);
|
||||
ValueEffectControl continuation =
|
||||
BuildPropertyAccess(receiver, value, context, frame_state_lazy, effect,
|
||||
control, name, access_info, access_mode);
|
||||
value = continuation.value();
|
||||
effect = continuation.effect();
|
||||
control = continuation.control();
|
||||
@ -287,7 +280,7 @@ Reduction JSNativeContextSpecialization::ReduceNamedAccess(
|
||||
// Generate the actual property access.
|
||||
ValueEffectControl continuation = BuildPropertyAccess(
|
||||
this_receiver, this_value, context, frame_state_lazy, this_effect,
|
||||
this_control, name, native_context, access_info, access_mode);
|
||||
this_control, name, access_info, access_mode);
|
||||
values.push_back(continuation.value());
|
||||
effects.push_back(continuation.effect());
|
||||
controls.push_back(continuation.control());
|
||||
@ -453,11 +446,8 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
||||
value = graph()->NewNode(simplified()->StringFromCharCode(), value);
|
||||
} else {
|
||||
// Retrieve the native context from the given {node}.
|
||||
Handle<Context> native_context;
|
||||
if (!GetNativeContext(node).ToHandle(&native_context)) return NoChange();
|
||||
|
||||
// Compute element access infos for the receiver maps.
|
||||
AccessInfoFactory access_info_factory(dependencies(), native_context,
|
||||
AccessInfoFactory access_info_factory(dependencies(), native_context(),
|
||||
graph()->zone());
|
||||
ZoneVector<ElementAccessInfo> access_infos(zone());
|
||||
if (!access_info_factory.ComputeElementAccessInfos(
|
||||
@ -543,9 +533,9 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
||||
access_info.receiver_maps());
|
||||
|
||||
// Access the actual element.
|
||||
ValueEffectControl continuation = BuildElementAccess(
|
||||
receiver, index, value, effect, control, native_context, access_info,
|
||||
access_mode, store_mode);
|
||||
ValueEffectControl continuation =
|
||||
BuildElementAccess(receiver, index, value, effect, control,
|
||||
access_info, access_mode, store_mode);
|
||||
value = continuation.value();
|
||||
effect = continuation.effect();
|
||||
control = continuation.control();
|
||||
@ -644,7 +634,7 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
||||
// Access the actual element.
|
||||
ValueEffectControl continuation = BuildElementAccess(
|
||||
this_receiver, this_index, this_value, this_effect, this_control,
|
||||
native_context, access_info, access_mode, store_mode);
|
||||
access_info, access_mode, store_mode);
|
||||
values.push_back(continuation.value());
|
||||
effects.push_back(continuation.effect());
|
||||
controls.push_back(continuation.control());
|
||||
@ -805,12 +795,12 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
|
||||
JSNativeContextSpecialization::ValueEffectControl
|
||||
JSNativeContextSpecialization::BuildPropertyAccess(
|
||||
Node* receiver, Node* value, Node* context, Node* frame_state, Node* effect,
|
||||
Node* control, Handle<Name> name, Handle<Context> native_context,
|
||||
PropertyAccessInfo const& access_info, AccessMode access_mode) {
|
||||
Node* control, Handle<Name> name, PropertyAccessInfo const& access_info,
|
||||
AccessMode access_mode) {
|
||||
// Determine actual holder and perform prototype chain checks.
|
||||
Handle<JSObject> holder;
|
||||
if (access_info.holder().ToHandle(&holder)) {
|
||||
AssumePrototypesStable(access_info.receiver_maps(), native_context, holder);
|
||||
AssumePrototypesStable(access_info.receiver_maps(), holder);
|
||||
}
|
||||
|
||||
// Generate the actual property access.
|
||||
@ -1058,8 +1048,8 @@ ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) {
|
||||
JSNativeContextSpecialization::ValueEffectControl
|
||||
JSNativeContextSpecialization::BuildElementAccess(
|
||||
Node* receiver, Node* index, Node* value, Node* effect, Node* control,
|
||||
Handle<Context> native_context, ElementAccessInfo const& access_info,
|
||||
AccessMode access_mode, KeyedAccessStoreMode store_mode) {
|
||||
ElementAccessInfo const& access_info, AccessMode access_mode,
|
||||
KeyedAccessStoreMode store_mode) {
|
||||
// TODO(bmeurer): We currently specialize based on elements kind. We should
|
||||
// also be able to properly support strings and other JSObjects here.
|
||||
ElementsKind elements_kind = access_info.elements_kind();
|
||||
@ -1234,7 +1224,7 @@ JSNativeContextSpecialization::BuildElementAccess(
|
||||
if (elements_kind == FAST_HOLEY_ELEMENTS ||
|
||||
elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
|
||||
// Check if we are allowed to turn the hole into undefined.
|
||||
if (CanTreatHoleAsUndefined(receiver_maps, native_context)) {
|
||||
if (CanTreatHoleAsUndefined(receiver_maps)) {
|
||||
// Turn the hole into undefined.
|
||||
value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
|
||||
value);
|
||||
@ -1247,7 +1237,7 @@ JSNativeContextSpecialization::BuildElementAccess(
|
||||
// Perform the hole check on the result.
|
||||
CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
|
||||
// Check if we are allowed to return the hole directly.
|
||||
if (CanTreatHoleAsUndefined(receiver_maps, native_context)) {
|
||||
if (CanTreatHoleAsUndefined(receiver_maps)) {
|
||||
// Return the signaling NaN hole directly if all uses are truncating.
|
||||
mode = CheckFloat64HoleMode::kAllowReturnHole;
|
||||
}
|
||||
@ -1357,14 +1347,13 @@ Node* JSNativeContextSpecialization::BuildCheckHeapObject(Node* receiver,
|
||||
}
|
||||
|
||||
void JSNativeContextSpecialization::AssumePrototypesStable(
|
||||
std::vector<Handle<Map>> const& receiver_maps,
|
||||
Handle<Context> native_context, Handle<JSObject> holder) {
|
||||
std::vector<Handle<Map>> const& receiver_maps, Handle<JSObject> holder) {
|
||||
// Determine actual holder and perform prototype chain checks.
|
||||
for (auto map : receiver_maps) {
|
||||
// Perform the implicit ToObject for primitives here.
|
||||
// Implemented according to ES6 section 7.3.2 GetV (V, P).
|
||||
Handle<JSFunction> constructor;
|
||||
if (Map::GetConstructorFunction(map, native_context)
|
||||
if (Map::GetConstructorFunction(map, native_context())
|
||||
.ToHandle(&constructor)) {
|
||||
map = handle(constructor->initial_map(), isolate());
|
||||
}
|
||||
@ -1373,16 +1362,15 @@ void JSNativeContextSpecialization::AssumePrototypesStable(
|
||||
}
|
||||
|
||||
bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
|
||||
std::vector<Handle<Map>> const& receiver_maps,
|
||||
Handle<Context> native_context) {
|
||||
std::vector<Handle<Map>> const& receiver_maps) {
|
||||
// Check if the array prototype chain is intact.
|
||||
if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false;
|
||||
|
||||
// Make sure both the initial Array and Object prototypes are stable.
|
||||
Handle<JSObject> initial_array_prototype(
|
||||
native_context->initial_array_prototype(), isolate());
|
||||
native_context()->initial_array_prototype(), isolate());
|
||||
Handle<JSObject> initial_object_prototype(
|
||||
native_context->initial_object_prototype(), isolate());
|
||||
native_context()->initial_object_prototype(), isolate());
|
||||
if (!initial_array_prototype->map()->is_stable() ||
|
||||
!initial_object_prototype->map()->is_stable()) {
|
||||
return false;
|
||||
@ -1491,44 +1479,30 @@ MaybeHandle<Map> JSNativeContextSpecialization::InferReceiverRootMap(
|
||||
return MaybeHandle<Map>();
|
||||
}
|
||||
|
||||
MaybeHandle<Context> JSNativeContextSpecialization::GetNativeContext(
|
||||
Node* node) {
|
||||
Node* const context = NodeProperties::GetContextInput(node);
|
||||
return NodeProperties::GetSpecializationNativeContext(context,
|
||||
native_context());
|
||||
}
|
||||
|
||||
|
||||
Graph* JSNativeContextSpecialization::graph() const {
|
||||
return jsgraph()->graph();
|
||||
}
|
||||
|
||||
|
||||
Isolate* JSNativeContextSpecialization::isolate() const {
|
||||
return jsgraph()->isolate();
|
||||
}
|
||||
|
||||
|
||||
Factory* JSNativeContextSpecialization::factory() const {
|
||||
return isolate()->factory();
|
||||
}
|
||||
|
||||
|
||||
MachineOperatorBuilder* JSNativeContextSpecialization::machine() const {
|
||||
return jsgraph()->machine();
|
||||
}
|
||||
|
||||
|
||||
CommonOperatorBuilder* JSNativeContextSpecialization::common() const {
|
||||
return jsgraph()->common();
|
||||
}
|
||||
|
||||
|
||||
JSOperatorBuilder* JSNativeContextSpecialization::javascript() const {
|
||||
return jsgraph()->javascript();
|
||||
}
|
||||
|
||||
|
||||
SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const {
|
||||
return jsgraph()->simplified();
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
|
||||
typedef base::Flags<Flag> Flags;
|
||||
|
||||
JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph, Flags flags,
|
||||
MaybeHandle<Context> native_context,
|
||||
Handle<Context> native_context,
|
||||
CompilationDependencies* dependencies,
|
||||
Zone* zone);
|
||||
|
||||
@ -103,15 +103,16 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
|
||||
Node* context, Node* frame_state,
|
||||
Node* effect, Node* control,
|
||||
Handle<Name> name,
|
||||
Handle<Context> native_context,
|
||||
PropertyAccessInfo const& access_info,
|
||||
AccessMode access_mode);
|
||||
|
||||
// Construct the appropriate subgraph for element access.
|
||||
ValueEffectControl BuildElementAccess(
|
||||
Node* receiver, Node* index, Node* value, Node* effect, Node* control,
|
||||
Handle<Context> native_context, ElementAccessInfo const& access_info,
|
||||
AccessMode access_mode, KeyedAccessStoreMode store_mode);
|
||||
ValueEffectControl BuildElementAccess(Node* receiver, Node* index,
|
||||
Node* value, Node* effect,
|
||||
Node* control,
|
||||
ElementAccessInfo const& access_info,
|
||||
AccessMode access_mode,
|
||||
KeyedAccessStoreMode store_mode);
|
||||
|
||||
// Construct an appropriate map check.
|
||||
Node* BuildCheckMaps(Node* receiver, Node* effect, Node* control,
|
||||
@ -123,14 +124,12 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
|
||||
// Adds stability dependencies on all prototypes of every class in
|
||||
// {receiver_type} up to (and including) the {holder}.
|
||||
void AssumePrototypesStable(std::vector<Handle<Map>> const& receiver_maps,
|
||||
Handle<Context> native_context,
|
||||
Handle<JSObject> holder);
|
||||
|
||||
// Checks if we can turn the hole into undefined when loading an element
|
||||
// from an object with one of the {receiver_maps}; sets up appropriate
|
||||
// code dependencies and might use the array protector cell.
|
||||
bool CanTreatHoleAsUndefined(std::vector<Handle<Map>> const& receiver_maps,
|
||||
Handle<Context> native_context);
|
||||
bool CanTreatHoleAsUndefined(std::vector<Handle<Map>> const& receiver_maps);
|
||||
|
||||
// Extract receiver maps from {nexus} and filter based on {receiver} if
|
||||
// possible.
|
||||
@ -146,9 +145,6 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
|
||||
// program location.
|
||||
MaybeHandle<Map> InferReceiverRootMap(Node* receiver);
|
||||
|
||||
// Retrieve the native context from the given {node} if known.
|
||||
MaybeHandle<Context> GetNativeContext(Node* node);
|
||||
|
||||
Graph* graph() const;
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
Isolate* isolate() const;
|
||||
@ -158,13 +154,13 @@ class JSNativeContextSpecialization final : public AdvancedReducer {
|
||||
SimplifiedOperatorBuilder* simplified() const;
|
||||
MachineOperatorBuilder* machine() const;
|
||||
Flags flags() const { return flags_; }
|
||||
MaybeHandle<Context> native_context() const { return native_context_; }
|
||||
Handle<Context> native_context() const { return native_context_; }
|
||||
CompilationDependencies* dependencies() const { return dependencies_; }
|
||||
Zone* zone() const { return zone_; }
|
||||
|
||||
JSGraph* const jsgraph_;
|
||||
Flags const flags_;
|
||||
MaybeHandle<Context> native_context_;
|
||||
Handle<Context> native_context_;
|
||||
CompilationDependencies* const dependencies_;
|
||||
Zone* const zone_;
|
||||
TypeCache const& type_cache_;
|
||||
|
@ -337,76 +337,6 @@ MaybeHandle<Context> NodeProperties::GetSpecializationContext(
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<Context> NodeProperties::GetSpecializationNativeContext(
|
||||
Node* node, MaybeHandle<Context> native_context) {
|
||||
while (true) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kJSLoadContext: {
|
||||
ContextAccess const& access = ContextAccessOf(node->op());
|
||||
if (access.index() != Context::NATIVE_CONTEXT_INDEX) {
|
||||
return MaybeHandle<Context>();
|
||||
}
|
||||
// Skip over the intermediate contexts, we're only interested in the
|
||||
// very last context in the context chain anyway.
|
||||
node = NodeProperties::GetContextInput(node);
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kJSCreateBlockContext:
|
||||
case IrOpcode::kJSCreateCatchContext:
|
||||
case IrOpcode::kJSCreateFunctionContext:
|
||||
case IrOpcode::kJSCreateScriptContext:
|
||||
case IrOpcode::kJSCreateWithContext: {
|
||||
// Skip over the intermediate contexts, we're only interested in the
|
||||
// very last context in the context chain anyway.
|
||||
node = NodeProperties::GetContextInput(node);
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kHeapConstant: {
|
||||
// Extract the native context from the actual {context}.
|
||||
Handle<Context> context =
|
||||
Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node));
|
||||
return handle(context->native_context());
|
||||
}
|
||||
case IrOpcode::kOsrGuard: {
|
||||
Node* osr_value = node->InputAt(0);
|
||||
DCHECK_EQ(IrOpcode::kOsrValue, osr_value->opcode());
|
||||
int const index = OsrValueIndexOf(osr_value->op());
|
||||
if (index == Linkage::kOsrContextSpillSlotIndex) {
|
||||
return native_context;
|
||||
}
|
||||
return MaybeHandle<Context>();
|
||||
}
|
||||
case IrOpcode::kParameter: {
|
||||
Node* const start = NodeProperties::GetValueInput(node, 0);
|
||||
DCHECK_EQ(IrOpcode::kStart, start->opcode());
|
||||
int const index = ParameterIndexOf(node->op());
|
||||
// The context is always the last parameter to a JavaScript function,
|
||||
// and {Parameter} indices start at -1, so value outputs of {Start}
|
||||
// look like this: closure, receiver, param0, ..., paramN, context.
|
||||
if (index == start->op()->ValueOutputCount() - 2) {
|
||||
return native_context;
|
||||
}
|
||||
return MaybeHandle<Context>();
|
||||
}
|
||||
default:
|
||||
return MaybeHandle<Context>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
MaybeHandle<JSGlobalObject> NodeProperties::GetSpecializationGlobalObject(
|
||||
Node* node, MaybeHandle<Context> native_context) {
|
||||
Handle<Context> context;
|
||||
if (GetSpecializationNativeContext(node, native_context).ToHandle(&context)) {
|
||||
return handle(context->global_object());
|
||||
}
|
||||
return MaybeHandle<JSGlobalObject>();
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Type* NodeProperties::GetTypeOrAny(Node* node) {
|
||||
return IsTyped(node) ? node->type() : Type::Any();
|
||||
|
@ -131,18 +131,6 @@ class NodeProperties final {
|
||||
static MaybeHandle<Context> GetSpecializationContext(
|
||||
Node* node, MaybeHandle<Context> context = MaybeHandle<Context>());
|
||||
|
||||
// Try to retrieve the specialization native context from the given
|
||||
// {node}, optionally utilizing the knowledge about the (outermost)
|
||||
// {native_context}.
|
||||
static MaybeHandle<Context> GetSpecializationNativeContext(
|
||||
Node* node, MaybeHandle<Context> native_context = MaybeHandle<Context>());
|
||||
|
||||
// Try to retrieve the specialization global object from the given
|
||||
// {node}, optionally utilizing the knowledge about the (outermost)
|
||||
// {native_context}.
|
||||
static MaybeHandle<JSGlobalObject> GetSpecializationGlobalObject(
|
||||
Node* node, MaybeHandle<Context> native_context = MaybeHandle<Context>());
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Type.
|
||||
|
||||
|
@ -186,11 +186,11 @@ class PipelineData {
|
||||
CommonOperatorBuilder* common() const { return common_; }
|
||||
JSOperatorBuilder* javascript() const { return javascript_; }
|
||||
JSGraph* jsgraph() const { return jsgraph_; }
|
||||
MaybeHandle<Context> native_context() const {
|
||||
if (info()->is_native_context_specializing()) {
|
||||
return handle(info()->native_context(), isolate());
|
||||
}
|
||||
return MaybeHandle<Context>();
|
||||
Handle<Context> native_context() const {
|
||||
return handle(info()->native_context(), isolate());
|
||||
}
|
||||
Handle<JSGlobalObject> global_object() const {
|
||||
return handle(info()->global_object(), isolate());
|
||||
}
|
||||
|
||||
LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; }
|
||||
@ -603,9 +603,6 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() {
|
||||
if (!FLAG_always_opt) {
|
||||
info()->MarkAsBailoutOnUninitialized();
|
||||
}
|
||||
if (FLAG_native_context_specialization) {
|
||||
info()->MarkAsNativeContextSpecializing();
|
||||
}
|
||||
if (FLAG_turbo_inlining) {
|
||||
info()->MarkAsInliningEnabled();
|
||||
}
|
||||
@ -803,7 +800,7 @@ struct InliningPhase {
|
||||
JSFrameSpecialization frame_specialization(
|
||||
&graph_reducer, data->info()->osr_frame(), data->jsgraph());
|
||||
JSGlobalObjectSpecialization global_object_specialization(
|
||||
&graph_reducer, data->jsgraph(), data->native_context(),
|
||||
&graph_reducer, data->jsgraph(), data->global_object(),
|
||||
data->info()->dependencies());
|
||||
JSNativeContextSpecialization::Flags flags =
|
||||
JSNativeContextSpecialization::kNoFlags;
|
||||
@ -931,10 +928,7 @@ struct TypedLoweringPhase {
|
||||
? JSBuiltinReducer::kDeoptimizationEnabled
|
||||
: JSBuiltinReducer::kNoFlags,
|
||||
data->info()->dependencies());
|
||||
MaybeHandle<LiteralsArray> literals_array =
|
||||
data->info()->is_native_context_specializing()
|
||||
? handle(data->info()->closure()->literals(), data->isolate())
|
||||
: MaybeHandle<LiteralsArray>();
|
||||
Handle<LiteralsArray> literals_array(data->info()->closure()->literals());
|
||||
JSCreateLowering create_lowering(
|
||||
&graph_reducer, data->info()->dependencies(), data->jsgraph(),
|
||||
literals_array, data->native_context(), temp_zone);
|
||||
|
@ -465,8 +465,6 @@ DEFINE_BOOL(turbo_source_positions, false,
|
||||
DEFINE_IMPLICATION(trace_turbo, turbo_source_positions)
|
||||
DEFINE_BOOL(function_context_specialization, false,
|
||||
"enable function context specialization in TurboFan")
|
||||
DEFINE_BOOL(native_context_specialization, true,
|
||||
"enable native context specialization in TurboFan")
|
||||
DEFINE_BOOL(turbo_inlining, true, "enable inlining in TurboFan")
|
||||
DEFINE_BOOL(trace_turbo_inlining, false, "trace TurboFan inlining")
|
||||
DEFINE_BOOL(turbo_load_elimination, true, "enable load elimination in TurboFan")
|
||||
|
@ -26,8 +26,7 @@ FunctionTester::FunctionTester(const char* source, uint32_t flags)
|
||||
function((FLAG_allow_natives_syntax = true, NewFunction(source))),
|
||||
flags_(flags) {
|
||||
Compile(function);
|
||||
const uint32_t supported_flags = CompilationInfo::kNativeContextSpecializing |
|
||||
CompilationInfo::kInliningEnabled;
|
||||
const uint32_t supported_flags = CompilationInfo::kInliningEnabled;
|
||||
CHECK_EQ(0u, flags_ & ~supported_flags);
|
||||
}
|
||||
|
||||
@ -164,9 +163,6 @@ Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
|
||||
|
||||
info.SetOptimizing();
|
||||
info.MarkAsDeoptimizationEnabled();
|
||||
if (flags_ & CompilationInfo::kNativeContextSpecializing) {
|
||||
info.MarkAsNativeContextSpecializing();
|
||||
}
|
||||
if (flags_ & CompilationInfo::kInliningEnabled) {
|
||||
info.MarkAsInliningEnabled();
|
||||
}
|
||||
|
@ -48,11 +48,9 @@ void InstallAssertInlineCountHelper(v8::Isolate* isolate) {
|
||||
.FromJust());
|
||||
}
|
||||
|
||||
const uint32_t kRestrictedInliningFlags =
|
||||
CompilationInfo::kNativeContextSpecializing;
|
||||
const uint32_t kRestrictedInliningFlags = 0;
|
||||
|
||||
const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled |
|
||||
CompilationInfo::kNativeContextSpecializing;
|
||||
const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -205,56 +205,6 @@ TEST(CallEval) {
|
||||
T.CheckCall(T.Val(42), T.Val("x"), T.undefined());
|
||||
}
|
||||
|
||||
|
||||
TEST(ContextLoadedFromActivation) {
|
||||
const char* script =
|
||||
"var x = 42;"
|
||||
"(function() {"
|
||||
" return function () { return x };"
|
||||
"})()";
|
||||
|
||||
// Disable context specialization.
|
||||
FunctionTester T(script);
|
||||
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
|
||||
v8::Context::Scope scope(context);
|
||||
v8::Local<v8::Value> value = CompileRun(script);
|
||||
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
|
||||
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
|
||||
jsfun->set_code(T.function->code());
|
||||
jsfun->set_shared(T.function->shared());
|
||||
jsfun->set_literals(T.function->literals());
|
||||
CHECK(context->Global()
|
||||
->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
|
||||
.FromJust());
|
||||
CompileRun("var x = 24;");
|
||||
ExpectInt32("foo();", 24);
|
||||
}
|
||||
|
||||
|
||||
TEST(BuiltinLoadedFromActivation) {
|
||||
const char* script =
|
||||
"var x = 42;"
|
||||
"(function() {"
|
||||
" return function () { return this; };"
|
||||
"})()";
|
||||
|
||||
// Disable context specialization.
|
||||
FunctionTester T(script);
|
||||
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
|
||||
v8::Context::Scope scope(context);
|
||||
v8::Local<v8::Value> value = CompileRun(script);
|
||||
i::Handle<i::Object> ofun = v8::Utils::OpenHandle(*value);
|
||||
i::Handle<i::JSFunction> jsfun = Handle<JSFunction>::cast(ofun);
|
||||
jsfun->set_code(T.function->code());
|
||||
jsfun->set_shared(T.function->shared());
|
||||
jsfun->set_literals(T.function->literals());
|
||||
CHECK(context->Global()
|
||||
->Set(context, v8_str("foo"), v8::Utils::CallableToLocal(jsfun))
|
||||
.FromJust());
|
||||
CompileRun("var x = 24;");
|
||||
ExpectObject("foo()", context->Global());
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -1,93 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
// Flags: --allow-natives-syntax --expose-gc --gc-interval=216
|
||||
// Flags: --nonative-context-specialization
|
||||
|
||||
function PrettyPrint() { return ""; }
|
||||
function fail() { }
|
||||
assertSame = function assertSame() { if (found === expected) { if (1 / found) return; } else if ((expected !== expected) && (found !== found)) { return; }; }; assertEquals = function assertEquals(expected, found, name_opt) { if ( expected) { fail(PrettyPrint()); } };
|
||||
assertTrue = function assertTrue() { assertEquals(); };
|
||||
assertThrows = function assertThrows(code, type_opt, cause_opt) { var threwException = true; try { if (typeof code == 'function') { code(); } else {; } threwException = false; } catch (e) { if (typeof type_opt == 'function') {; } if (arguments.length >= 3) {; } return; } };
|
||||
assertInstanceof = function assertInstanceof() { if (obj instanceof type) { var actualTypeName = null; var actualConstructor = Object.getPrototypeOf().constructor; if (typeof actualConstructor == "function") {; }; } };
|
||||
function modifyPropertyOrValue() { var names; try {; } catch(e) {; return; } if(!names) return; name = names[rand_value % names.length]; if (isNaN()); }
|
||||
function nop() {}
|
||||
var __v_5 = {};
|
||||
var __v_12 = {};
|
||||
var __v_13 = {};
|
||||
var __v_16 = {};
|
||||
function __f_0() {
|
||||
}
|
||||
(function (){
|
||||
function __f_6() {
|
||||
}
|
||||
a = __f_6();
|
||||
b = __f_6();
|
||||
name = "Array";
|
||||
})();
|
||||
(function (){
|
||||
function __f_1() {
|
||||
assertTrue();
|
||||
}
|
||||
__f_1();
|
||||
})();
|
||||
__v_10 = {
|
||||
}
|
||||
__v_11 = new Object();
|
||||
tailee1 = function() {
|
||||
"use strict";
|
||||
if (__v_12-- == 0) {
|
||||
}
|
||||
return nop();
|
||||
};
|
||||
%OptimizeFunctionOnNextCall(tailee1);
|
||||
assertEquals(__v_10, tailee1.call());
|
||||
__v_14 = 100000;
|
||||
gc();
|
||||
tailee2 = function() {
|
||||
"use strict";
|
||||
__v_14 = ((__v_14 | 0) - 1) | 0;
|
||||
if ((__v_14 | 0) === 0) {
|
||||
}
|
||||
};
|
||||
%OptimizeFunctionOnNextCall(tailee2);
|
||||
assertEquals(__v_11, tailee2.call());
|
||||
__v_13 = 999999;
|
||||
tailee3 = function() {
|
||||
"use strict";
|
||||
if (__v_13-- == 0) {
|
||||
}
|
||||
};
|
||||
%OptimizeFunctionOnNextCall(tailee3);
|
||||
assertEquals(__v_9, tailee3.call(__v_11, __v_9));
|
||||
tailee4 = function(px) {
|
||||
return nop(tailee4, this, px, undefined);
|
||||
};
|
||||
%OptimizeFunctionOnNextCall(tailee4);
|
||||
assertThrows(function() { tailee4.call(); });
|
||||
tailee5 = function() {
|
||||
return nop();
|
||||
};
|
||||
%OptimizeFunctionOnNextCall(tailee5);
|
||||
assertThrows(function() { tailee5.call(); });
|
||||
tailee6 = function() {
|
||||
}
|
||||
tailee7 = function( py, pz, pa, pb, pc) {
|
||||
return nop();
|
||||
};
|
||||
%OptimizeFunctionOnNextCall(tailee7);
|
||||
tailee7.call();
|
||||
|
||||
(function() {
|
||||
Number.prototype[0] = "a";
|
||||
Number.prototype[1] = "b";
|
||||
Object.defineProperty(Number.prototype, 2, {
|
||||
get: function() {
|
||||
}
|
||||
});
|
||||
Number.prototype.length = 3;
|
||||
Array.prototype.includes.call(5);
|
||||
})();
|
||||
var __v_9 = -8;
|
||||
var __v_20 = 0;
|
@ -13,7 +13,11 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
GraphTest::GraphTest(int num_parameters) : common_(zone()), graph_(zone()) {
|
||||
GraphTest::GraphTest(int num_parameters)
|
||||
: TestWithNativeContext(),
|
||||
TestWithIsolateAndZone(),
|
||||
common_(zone()),
|
||||
graph_(zone()) {
|
||||
graph()->SetStart(graph()->NewNode(common()->Start(num_parameters)));
|
||||
graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ namespace compiler {
|
||||
|
||||
using ::testing::Matcher;
|
||||
|
||||
|
||||
class GraphTest : public TestWithContext, public TestWithIsolateAndZone {
|
||||
class GraphTest : public virtual TestWithNativeContext,
|
||||
public virtual TestWithIsolateAndZone {
|
||||
public:
|
||||
explicit GraphTest(int num_parameters = 1);
|
||||
~GraphTest() override;
|
||||
|
@ -40,8 +40,8 @@ class JSCreateLoweringTest : public TypedGraphTest {
|
||||
// TODO(titzer): mock the GraphReducer here for better unit testing.
|
||||
GraphReducer graph_reducer(zone(), graph());
|
||||
JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph,
|
||||
MaybeHandle<LiteralsArray>(),
|
||||
MaybeHandle<Context>(), zone());
|
||||
MaybeHandle<LiteralsArray>(), native_context(),
|
||||
zone());
|
||||
return reducer.Reduce(node);
|
||||
}
|
||||
|
||||
|
@ -84,13 +84,17 @@ TestWithIsolateAndZone::~TestWithIsolateAndZone() {}
|
||||
|
||||
Factory* TestWithIsolate::factory() const { return isolate()->factory(); }
|
||||
|
||||
|
||||
base::RandomNumberGenerator* TestWithIsolate::random_number_generator() const {
|
||||
return isolate()->random_number_generator();
|
||||
}
|
||||
|
||||
|
||||
TestWithZone::~TestWithZone() {}
|
||||
|
||||
TestWithNativeContext::~TestWithNativeContext() {}
|
||||
|
||||
Handle<Context> TestWithNativeContext::native_context() const {
|
||||
return isolate()->native_context();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -95,7 +95,6 @@ class TestWithIsolate : public virtual ::v8::TestWithIsolate {
|
||||
DISALLOW_COPY_AND_ASSIGN(TestWithIsolate);
|
||||
};
|
||||
|
||||
|
||||
class TestWithZone : public virtual ::testing::Test {
|
||||
public:
|
||||
TestWithZone() : zone_(&allocator_) {}
|
||||
@ -110,7 +109,6 @@ class TestWithZone : public virtual ::testing::Test {
|
||||
DISALLOW_COPY_AND_ASSIGN(TestWithZone);
|
||||
};
|
||||
|
||||
|
||||
class TestWithIsolateAndZone : public virtual TestWithIsolate {
|
||||
public:
|
||||
TestWithIsolateAndZone() : zone_(&allocator_) {}
|
||||
@ -125,6 +123,18 @@ class TestWithIsolateAndZone : public virtual TestWithIsolate {
|
||||
DISALLOW_COPY_AND_ASSIGN(TestWithIsolateAndZone);
|
||||
};
|
||||
|
||||
class TestWithNativeContext : public virtual ::v8::TestWithContext,
|
||||
public virtual TestWithIsolate {
|
||||
public:
|
||||
TestWithNativeContext() {}
|
||||
virtual ~TestWithNativeContext();
|
||||
|
||||
Handle<Context> native_context() const;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TestWithNativeContext);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user