Commit 77c4ba07 authored by jochen's avatar jochen Committed by Commit bot

Store the ScopeInfo in WithContexts

This will allow for chaining ScopeInfos together to form the same chains
as contexts chains currently do.

BUG=v8:5215
R=mstarzinger@chromium.org,marja@chromium.org,bmeurer@chromium.org,rmcilroy@chromium.org

Review-Url: https://codereview.chromium.org/2314483002
Cr-Commit-Position: refs/heads/master@{#39192}
parent 71668bbb
......@@ -2081,7 +2081,8 @@ MaybeLocal<Function> ScriptCompiler::CompileFunctionInContext(
Utils::OpenHandle(*context_extensions[i]);
if (!extension->IsJSObject()) return Local<Function>();
i::Handle<i::JSFunction> closure(context->closure(), isolate);
context = factory->NewWithContext(closure, context, extension);
context = factory->NewWithContext(
closure, context, i::ScopeInfo::CreateForWithScope(isolate), extension);
}
i::Handle<i::Object> name_obj;
......
......@@ -241,6 +241,38 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
return scope_info;
}
Handle<ScopeInfo> ScopeInfo::CreateForWithScope(Isolate* isolate) {
const int length = kVariablePartIndex + 1;
Factory* factory = isolate->factory();
Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
// Encode the flags.
int flags =
ScopeTypeField::encode(WITH_SCOPE) | CallsEvalField::encode(false) |
LanguageModeField::encode(SLOPPY) | DeclarationScopeField::encode(false) |
ReceiverVariableField::encode(NONE) | HasNewTargetField::encode(false) |
FunctionVariableField::encode(NONE) | AsmModuleField::encode(false) |
AsmFunctionField::encode(false) | HasSimpleParametersField::encode(true) |
FunctionKindField::encode(kNormalFunction);
scope_info->SetFlags(flags);
scope_info->SetParameterCount(0);
scope_info->SetStackLocalCount(0);
scope_info->SetContextLocalCount(0);
int index = kVariablePartIndex;
DCHECK_EQ(index, scope_info->ParameterEntriesIndex());
DCHECK_EQ(index, scope_info->StackLocalFirstSlotIndex());
scope_info->set(index++, Smi::FromInt(0));
DCHECK_EQ(index, scope_info->StackLocalEntriesIndex());
DCHECK_EQ(index, scope_info->ReceiverEntryIndex());
DCHECK_EQ(index, scope_info->FunctionNameEntryIndex());
DCHECK_EQ(index, scope_info->length());
DCHECK_EQ(0, scope_info->ParameterCount());
DCHECK_EQ(Context::MIN_CONTEXT_SLOTS, scope_info->ContextLength());
return scope_info;
}
Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
DCHECK(isolate->bootstrapper()->IsActive());
......
......@@ -92,20 +92,14 @@ void SloppyBlockFunctionMap::Declare(Zone* zone, const AstRawString* name,
// ----------------------------------------------------------------------------
// Implementation of Scope
Scope::Scope(Zone* zone, ScopeType scope_type)
Scope::Scope(Zone* zone)
: zone_(zone),
outer_scope_(nullptr),
variables_(zone),
locals_(4, zone),
decls_(4, zone),
scope_type_(scope_type) {
DCHECK(scope_type == SCRIPT_SCOPE || scope_type == WITH_SCOPE);
scope_type_(SCRIPT_SCOPE) {
SetDefaults();
#ifdef DEBUG
if (scope_type == WITH_SCOPE) {
already_resolved_ = true;
}
#endif
}
Scope::Scope(Zone* zone, Scope* outer_scope, ScopeType scope_type)
......@@ -325,7 +319,8 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
while (!context->IsNativeContext()) {
if (context->IsWithContext() || context->IsDebugEvaluateContext()) {
// For scope analysis, debug-evaluate is equivalent to a with scope.
outer_scope = new (zone) Scope(zone, WITH_SCOPE);
outer_scope = new (zone)
Scope(zone, WITH_SCOPE, Handle<ScopeInfo>(context->scope_info()));
// TODO(yangguo): Remove once debug-evaluate properly keeps track of the
// function scope in which we are evaluating.
......
......@@ -402,7 +402,7 @@ class Scope: public ZoneObject {
void set_is_debug_evaluate_scope() { is_debug_evaluate_scope_ = true; }
protected:
explicit Scope(Zone* zone, ScopeType scope_type = SCRIPT_SCOPE);
explicit Scope(Zone* zone);
void set_language_mode(LanguageMode language_mode) {
is_strict_ = is_strict(language_mode);
......
......@@ -1236,7 +1236,8 @@ void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
VisitForValue(stmt->expression());
Node* value = environment()->Pop();
Node* object = BuildToObject(value, stmt->ToObjectId());
const Operator* op = javascript()->CreateWithContext();
Handle<ScopeInfo> scope_info = stmt->scope()->scope_info();
const Operator* op = javascript()->CreateWithContext(scope_info);
Node* context = NewNode(op, object, GetFunctionClosureForContext());
PrepareFrameState(context, stmt->EntryId());
VisitInScope(stmt->statement(), stmt->scope(), context);
......
......@@ -964,8 +964,10 @@ void BytecodeGraphBuilder::VisitCreateCatchContext() {
void BytecodeGraphBuilder::VisitCreateWithContext() {
Node* object =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::cast(
bytecode_iterator().GetConstantForIndexOperand(1));
const Operator* op = javascript()->CreateWithContext();
const Operator* op = javascript()->CreateWithContext(scope_info);
Node* context = NewNode(op, object, environment()->LookupAccumulator());
environment()->BindAccumulator(context);
}
......
......@@ -815,6 +815,7 @@ Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode());
Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
Node* object = NodeProperties::GetValueInput(node, 0);
Node* closure = NodeProperties::GetValueInput(node, 1);
Node* effect = NodeProperties::GetEffectInput(node);
......@@ -823,12 +824,20 @@ Reduction JSCreateLowering::ReduceJSCreateWithContext(Node* node) {
Node* native_context = effect = graph()->NewNode(
javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true),
context, context, effect);
AllocationBuilder a(jsgraph(), effect, control);
AllocationBuilder aa(jsgraph(), effect, control);
aa.Allocate(ContextExtension::kSize);
aa.Store(AccessBuilder::ForMap(), factory()->context_extension_map());
aa.Store(AccessBuilder::ForContextExtensionScopeInfo(), scope_info);
aa.Store(AccessBuilder::ForContextExtensionExtension(), object);
Node* extension = aa.Finish();
AllocationBuilder a(jsgraph(), extension, control);
STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered.
a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map());
a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure);
a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context);
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), object);
a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension);
a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX),
native_context);
RelaxControls(node);
......
......@@ -45,13 +45,6 @@ Reduction JSGenericLowering::Reduce(Node* node) {
}
return Changed(node);
}
#define REPLACE_RUNTIME_CALL(op, fun) \
void JSGenericLowering::Lower##op(Node* node) { \
ReplaceWithRuntimeCall(node, fun); \
}
REPLACE_RUNTIME_CALL(JSCreateWithContext, Runtime::kPushWithContext)
REPLACE_RUNTIME_CALL(JSConvertReceiver, Runtime::kConvertReceiver)
#undef REPLACE_RUNTIME_CALL
#define REPLACE_STUB_CALL(Name) \
void JSGenericLowering::LowerJS##Name(Node* node) { \
......@@ -518,6 +511,11 @@ void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
}
void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
ReplaceWithRuntimeCall(node, Runtime::kPushWithContext);
}
void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
......@@ -577,6 +575,9 @@ void JSGenericLowering::LowerJSCallRuntime(Node* node) {
ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
}
void JSGenericLowering::LowerJSConvertReceiver(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kConvertReceiver);
}
void JSGenericLowering::LowerJSForInNext(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kForInNext);
......
......@@ -451,8 +451,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(LoadMessage, Operator::kNoThrow, 0, 1) \
V(StoreMessage, Operator::kNoThrow, 1, 0) \
V(GeneratorRestoreContinuation, Operator::kNoThrow, 1, 1) \
V(StackCheck, Operator::kNoWrite, 0, 0) \
V(CreateWithContext, Operator::kNoProperties, 2, 1)
V(StackCheck, Operator::kNoWrite, 0, 0)
#define BINARY_OP_LIST(V) \
V(BitwiseOr) \
......@@ -850,6 +849,14 @@ const Operator* JSOperatorBuilder::CreateCatchContext(
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateWithContext(
const Handle<ScopeInfo>& scope_info) {
return new (zone()) Operator1<Handle<ScopeInfo>>(
IrOpcode::kJSCreateWithContext, Operator::kNoProperties, // opcode
"JSCreateWithContext", // name
2, 1, 1, 1, 1, 2, // counts
scope_info); // parameter
}
const Operator* JSOperatorBuilder::CreateBlockContext(
const Handle<ScopeInfo>& scpope_info) {
......
......@@ -510,7 +510,7 @@ class JSOperatorBuilder final : public ZoneObject {
const Operator* CreateFunctionContext(int slot_count);
const Operator* CreateCatchContext(const Handle<String>& name,
const Handle<ScopeInfo>& scope_info);
const Operator* CreateWithContext();
const Operator* CreateWithContext(const Handle<ScopeInfo>& scope_info);
const Operator* CreateBlockContext(const Handle<ScopeInfo>& scpope_info);
const Operator* CreateModuleContext();
const Operator* CreateScriptContext(const Handle<ScopeInfo>& scpope_info);
......
......@@ -101,20 +101,21 @@ JSObject* Context::extension_object() {
return JSObject::cast(object);
}
JSReceiver* Context::extension_receiver() {
DCHECK(IsNativeContext() || IsWithContext() ||
IsFunctionContext() || IsBlockContext());
return IsWithContext() ? JSReceiver::cast(extension()) : extension_object();
return IsWithContext() ? JSReceiver::cast(
ContextExtension::cast(extension())->extension())
: extension_object();
}
ScopeInfo* Context::scope_info() {
DCHECK(IsModuleContext() || IsScriptContext() || IsBlockContext() ||
IsCatchContext());
IsCatchContext() || IsWithContext() || IsDebugEvaluateContext());
HeapObject* object = extension();
if (object->IsContextExtension()) {
DCHECK(IsBlockContext() || IsCatchContext());
DCHECK(IsBlockContext() || IsCatchContext() || IsWithContext() ||
IsDebugEvaluateContext());
object = ContextExtension::cast(object)->scope_info();
}
return ScopeInfo::cast(object);
......@@ -340,18 +341,21 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
} else if (context->IsDebugEvaluateContext()) {
// Check materialized locals.
Object* obj = context->get(EXTENSION_INDEX);
if (obj->IsJSReceiver()) {
Handle<JSReceiver> extension(JSReceiver::cast(obj));
LookupIterator it(extension, name, extension);
Maybe<bool> found = JSReceiver::HasProperty(&it);
if (found.FromMaybe(false)) {
*attributes = NONE;
return extension;
Object* ext = context->get(EXTENSION_INDEX);
if (ext->IsContextExtension()) {
Object* obj = ContextExtension::cast(ext)->extension();
if (obj->IsJSReceiver()) {
Handle<JSReceiver> extension(JSReceiver::cast(obj));
LookupIterator it(extension, name, extension);
Maybe<bool> found = JSReceiver::HasProperty(&it);
if (found.FromMaybe(false)) {
*attributes = NONE;
return extension;
}
}
}
// Check the original context, but do not follow its context chain.
obj = context->get(WRAPPED_CONTEXT_INDEX);
Object* obj = context->get(WRAPPED_CONTEXT_INDEX);
if (obj->IsContext()) {
Handle<Object> result =
Context::cast(obj)->Lookup(name, DONT_FOLLOW_CHAINS, index,
......
......@@ -94,7 +94,8 @@ MaybeHandle<Object> DebugEvaluate::Evaluate(
if (context_extension->IsJSObject()) {
Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
Handle<JSFunction> closure(context->closure(), isolate);
context = isolate->factory()->NewWithContext(closure, context, extension);
context = isolate->factory()->NewWithContext(
closure, context, ScopeInfo::CreateForWithScope(isolate), extension);
}
Handle<JSFunction> eval_fun;
......@@ -204,7 +205,8 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
for (int i = context_chain_.length() - 1; i >= 0; i--) {
evaluation_context_ = factory->NewDebugEvaluateContext(
evaluation_context_, context_chain_[i].materialized_object,
evaluation_context_, ScopeInfo::CreateForWithScope(isolate),
context_chain_[i].materialized_object,
context_chain_[i].wrapped_context, context_chain_[i].whitelist);
}
}
......
......@@ -834,17 +834,21 @@ Handle<Context> Factory::NewCatchContext(Handle<JSFunction> function,
}
Handle<Context> Factory::NewDebugEvaluateContext(Handle<Context> previous,
Handle<ScopeInfo> scope_info,
Handle<JSReceiver> extension,
Handle<Context> wrapped,
Handle<StringSet> whitelist) {
STATIC_ASSERT(Context::WHITE_LIST_INDEX == Context::MIN_CONTEXT_SLOTS + 1);
Handle<ContextExtension> context_extension = NewContextExtension(
scope_info, extension.is_null() ? Handle<Object>::cast(undefined_value())
: Handle<Object>::cast(extension));
Handle<FixedArray> array = NewFixedArray(Context::MIN_CONTEXT_SLOTS + 2);
array->set_map_no_write_barrier(*debug_evaluate_context_map());
Handle<Context> c = Handle<Context>::cast(array);
c->set_closure(wrapped.is_null() ? previous->closure() : wrapped->closure());
c->set_previous(*previous);
c->set_native_context(previous->native_context());
if (!extension.is_null()) c->set(Context::EXTENSION_INDEX, *extension);
c->set_extension(*context_extension);
if (!wrapped.is_null()) c->set(Context::WRAPPED_CONTEXT_INDEX, *wrapped);
if (!whitelist.is_null()) c->set(Context::WHITE_LIST_INDEX, *whitelist);
return c;
......@@ -852,13 +856,16 @@ Handle<Context> Factory::NewDebugEvaluateContext(Handle<Context> previous,
Handle<Context> Factory::NewWithContext(Handle<JSFunction> function,
Handle<Context> previous,
Handle<ScopeInfo> scope_info,
Handle<JSReceiver> extension) {
Handle<ContextExtension> context_extension =
NewContextExtension(scope_info, extension);
Handle<FixedArray> array = NewFixedArray(Context::MIN_CONTEXT_SLOTS);
array->set_map_no_write_barrier(*with_context_map());
Handle<Context> context = Handle<Context>::cast(array);
context->set_closure(*function);
context->set_previous(*previous);
context->set_extension(*extension);
context->set_extension(*context_extension);
context->set_native_context(previous->native_context());
return context;
}
......
......@@ -272,9 +272,11 @@ class Factory final {
// Create a 'with' context.
Handle<Context> NewWithContext(Handle<JSFunction> function,
Handle<Context> previous,
Handle<ScopeInfo> scope_info,
Handle<JSReceiver> extension);
Handle<Context> NewDebugEvaluateContext(Handle<Context> previous,
Handle<ScopeInfo> scope_info,
Handle<JSReceiver> extension,
Handle<Context> wrapped,
Handle<StringSet> whitelist);
......
......@@ -1135,6 +1135,7 @@ void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
RestoreContext();
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PushOperand(result_register());
PushOperand(stmt->scope()->scope_info());
PushFunctionArgumentForContextAllocation();
CallRuntimeWithOperands(Runtime::kPushWithContext);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
......
......@@ -363,8 +363,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) {
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(Register object) {
Output(Bytecode::kCreateWithContext, RegisterOperand(object));
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext(
Register object, Handle<ScopeInfo> scope_info) {
size_t scope_info_index = GetConstantPoolEntry(scope_info);
Output(Bytecode::kCreateWithContext, RegisterOperand(object),
UnsignedOperand(scope_info_index));
return *this;
}
......
......@@ -148,9 +148,10 @@ class BytecodeArrayBuilder final : public ZoneObject {
// Create a new context with size |slots|.
BytecodeArrayBuilder& CreateFunctionContext(int slots);
// Creates a new context for a with-statement with the |object| in a register
// and the closure in the accumulator.
BytecodeArrayBuilder& CreateWithContext(Register object);
// Creates a new context with the given |scope_info| for a with-statement
// with the |object| in a register and the closure in the accumulator.
BytecodeArrayBuilder& CreateWithContext(Register object,
Handle<ScopeInfo> scope_info);
// Create a new arguments object in the accumulator.
BytecodeArrayBuilder& CreateArguments(CreateArgumentsType type);
......
......@@ -1092,7 +1092,7 @@ void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
builder()->SetStatementPosition(stmt);
VisitForAccumulatorValue(stmt->expression());
VisitNewLocalWithContext();
VisitNewLocalWithContext(stmt->scope());
VisitInScope(stmt->statement(), stmt->scope());
}
......@@ -3198,14 +3198,14 @@ void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
execution_result()->SetResultInAccumulator();
}
void BytecodeGenerator::VisitNewLocalWithContext() {
void BytecodeGenerator::VisitNewLocalWithContext(Scope* scope) {
AccumulatorResultScope accumulator_execution_result(this);
Register extension_object = register_allocator()->NewRegister();
builder()->ConvertAccumulatorToObject(extension_object);
VisitFunctionClosureForContext();
builder()->CreateWithContext(extension_object);
builder()->CreateWithContext(extension_object, scope->scope_info());
execution_result()->SetResultInAccumulator();
}
......
......@@ -141,7 +141,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void VisitBlockDeclarationsAndStatements(Block* stmt);
void VisitNewLocalBlockContext(Scope* scope);
void VisitNewLocalCatchContext(Variable* variable, Scope* scope);
void VisitNewLocalWithContext();
void VisitNewLocalWithContext(Scope* scope);
void VisitFunctionClosureForContext();
void VisitSetHomeObject(Register value, Register home_object,
ObjectLiteralProperty* property, int slot_number = 0);
......
......@@ -248,7 +248,8 @@ namespace interpreter {
OperandType::kIdx, OperandType::kIdx) \
/* TODO(klaasb) rename Idx or add unsigned Imm OperandType? */ \
V(CreateFunctionContext, AccumulatorUse::kWrite, OperandType::kIdx) \
V(CreateWithContext, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(CreateWithContext, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
\
/* Arguments allocation */ \
V(CreateMappedArguments, AccumulatorUse::kWrite) \
......
......@@ -2022,17 +2022,20 @@ void Interpreter::DoCreateFunctionContext(InterpreterAssembler* assembler) {
__ Dispatch();
}
// CreateWithContext <register>
// CreateWithContext <register> <scope_info_idx>
//
// Creates a new context for a with-statement with the object in |register| and
// the closure in the accumulator.
// Creates a new context with the ScopeInfo at |scope_info_idx| for a
// with-statement with the object in |register| and the closure in the
// accumulator.
void Interpreter::DoCreateWithContext(InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0);
Node* object = __ LoadRegister(reg_index);
Node* scope_info_idx = __ BytecodeOperandIdx(1);
Node* scope_info = __ LoadConstantPoolEntry(scope_info_idx);
Node* closure = __ GetAccumulator();
Node* context = __ GetContext();
__ SetAccumulator(
__ CallRuntime(Runtime::kPushWithContext, context, object, closure));
__ SetAccumulator(__ CallRuntime(Runtime::kPushWithContext, context, object,
scope_info, closure));
__ Dispatch();
}
......
......@@ -4392,6 +4392,7 @@ class ScopeInfo : public FixedArray {
FunctionKind function_kind();
static Handle<ScopeInfo> Create(Isolate* isolate, Zone* zone, Scope* scope);
static Handle<ScopeInfo> CreateForWithScope(Isolate* isolate);
static Handle<ScopeInfo> CreateGlobalThisBinding(Isolate* isolate);
// Serializes empty scope info.
......
......@@ -688,12 +688,13 @@ RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
RUNTIME_FUNCTION(Runtime_PushWithContext) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
Handle<Context> current(isolate->context());
Handle<Context> context =
isolate->factory()->NewWithContext(function, current, extension_object);
Handle<Context> context = isolate->factory()->NewWithContext(
function, current, scope_info, extension_object);
isolate->set_context(*context);
return *context;
}
......
......@@ -474,7 +474,7 @@ namespace internal {
F(NewClosure_Tenured, 1, 1) \
F(NewScriptContext, 2, 1) \
F(NewFunctionContext, 1, 1) \
F(PushWithContext, 2, 1) \
F(PushWithContext, 3, 1) \
F(PushCatchContext, 4, 1) \
F(PushBlockContext, 2, 1) \
F(DeleteLookupSlot, 1, 1) \
......
......@@ -13,20 +13,21 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 21
bytecode array length: 22
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(1),
B(Ldar), R(1),
B(ToObject), R(2),
B(Ldar), R(closure),
B(CreateWithContext), R(2),
B(CreateWithContext), R(2), U8(1),
B(PushContext), R(0),
/* 50 S> */ B(LdaLookupSlot), U8(1),
/* 50 S> */ B(LdaLookupSlot), U8(2),
B(PopContext), R(0),
/* 62 S> */ B(Return),
]
constant pool: [
InstanceType::FIXED_ARRAY_TYPE,
InstanceType::FIXED_ARRAY_TYPE,
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
]
......
......@@ -174,14 +174,15 @@ TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
// JSCreateWithContext
TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
Handle<ScopeInfo> scope_info(factory()->NewScopeInfo(1));
Node* const object = Parameter(Type::Receiver());
Node* const closure = Parameter(Type::Function());
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->CreateWithContext(), object,
closure, context, effect, control));
Reduce(graph()->NewNode(javascript()->CreateWithContext(scope_info),
object, closure, context, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
......
......@@ -46,7 +46,6 @@ const SharedOperator kSharedOperators[] = {
SHARED(ToObject, Operator::kFoldable, 1, 1, 1, 1, 1, 1, 2),
SHARED(Create, Operator::kEliminatable, 2, 1, 1, 0, 1, 1, 0),
SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0, 0),
SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1, 2),
#undef SHARED
};
......
......@@ -107,7 +107,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.CreateBlockContext(factory->NewScopeInfo(1));
builder.CreateCatchContext(reg, name, factory->NewScopeInfo(1));
builder.CreateFunctionContext(1);
builder.CreateWithContext(reg);
builder.CreateWithContext(reg, factory->NewScopeInfo(1));
// Emit literal creation operations.
builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("a"), 0, 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment