From 371af773cf1982a375df89c80922540f4f57ebbe Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Thu, 9 Jun 2011 11:26:01 +0000 Subject: [PATCH] A collection of context-related refactoring changes. Introduce separate maps for function and with contexts. Use the function context map for testing whether a context is a function context (global contexts are no longer function contexts). Split the paths for allocating with and catch contexts. Rename some functions. Generally refactor code to make it simpler. R=ager@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/7003058 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 4 +- src/arm/full-codegen-arm.cc | 2 +- src/arm/lithium-codegen-arm.cc | 2 +- src/ast.cc | 4 +- src/ast.h | 16 ++--- src/contexts.cc | 15 ++-- src/contexts.h | 13 +++- src/factory.cc | 16 +++-- src/factory.h | 7 +- src/full-codegen.cc | 19 ++--- src/heap.cc | 43 ++++++++---- src/heap.h | 9 ++- src/hydrogen.cc | 9 +-- src/ia32/code-stubs-ia32.cc | 5 +- src/ia32/full-codegen-ia32.cc | 2 +- src/ia32/lithium-codegen-ia32.cc | 2 +- src/mark-compact.cc | 3 +- src/objects-inl.h | 17 ++--- src/objects.h | 1 - src/parser.cc | 10 +-- src/prettyprinter.cc | 27 ++++---- src/rewriter.cc | 129 +++------------------------------- src/runtime.cc | 146 +++++++++++++++++++-------------------- src/runtime.h | 4 +- src/x64/code-stubs-x64.cc | 4 +- src/x64/full-codegen-x64.cc | 2 +- src/x64/lithium-codegen-x64.cc | 2 +- 27 files changed, 218 insertions(+), 295 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index 34b9458..6f6d13d 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -158,7 +158,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { __ ldr(r3, MemOperand(sp, 0)); // Setup the object header. - __ LoadRoot(r2, Heap::kContextMapRootIndex); + __ LoadRoot(r2, Heap::kFunctionContextMapRootIndex); __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); __ mov(r2, Operand(Smi::FromInt(length))); __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); @@ -187,7 +187,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Need to collect. Call into runtime system. __ bind(&gc); - __ TailCallRuntime(Runtime::kNewContext, 1, 1); + __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1); } diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 434abf2..b0cc8fc 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -182,7 +182,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { FastNewContextStub stub(heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } function_in_register = false; // Context is returned in both r0 and cp. It replaces the context diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 86be095..6c57c53 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -189,7 +189,7 @@ bool LCodeGen::GeneratePrologue() { FastNewContextStub stub(heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } RecordSafepoint(Safepoint::kNoDeoptimizationIndex); // Context is returned in both r0 and cp. It replaces the context diff --git a/src/ast.cc b/src/ast.cc index 21d7007..523b6ee 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -362,12 +362,12 @@ bool ForInStatement::IsInlineable() const { } -bool WithEnterStatement::IsInlineable() const { +bool EnterWithContextStatement::IsInlineable() const { return false; } -bool WithExitStatement::IsInlineable() const { +bool ExitContextStatement::IsInlineable() const { return false; } diff --git a/src/ast.h b/src/ast.h index 7ed3579..92b6687 100644 --- a/src/ast.h +++ b/src/ast.h @@ -60,8 +60,8 @@ namespace internal { V(ContinueStatement) \ V(BreakStatement) \ V(ReturnStatement) \ - V(WithEnterStatement) \ - V(WithExitStatement) \ + V(EnterWithContextStatement) \ + V(ExitContextStatement) \ V(SwitchStatement) \ V(DoWhileStatement) \ V(WhileStatement) \ @@ -611,12 +611,12 @@ class ReturnStatement: public Statement { }; -class WithEnterStatement: public Statement { +class EnterWithContextStatement: public Statement { public: - explicit WithEnterStatement(Expression* expression) + explicit EnterWithContextStatement(Expression* expression) : expression_(expression) { } - DECLARE_NODE_TYPE(WithEnterStatement) + DECLARE_NODE_TYPE(EnterWithContextStatement) Expression* expression() const { return expression_; } @@ -627,13 +627,11 @@ class WithEnterStatement: public Statement { }; -class WithExitStatement: public Statement { +class ExitContextStatement: public Statement { public: - WithExitStatement() { } - virtual bool IsInlineable() const; - DECLARE_NODE_TYPE(WithExitStatement) + DECLARE_NODE_TYPE(ExitContextStatement) }; diff --git a/src/contexts.cc b/src/contexts.cc index f6031f1..ec9a1b3 100644 --- a/src/contexts.cc +++ b/src/contexts.cc @@ -96,7 +96,7 @@ Handle Context::Lookup(Handle name, ContextLookupFlags flags, PrintF("\n"); } - // check extension/with object + // Check extension/with/global object. if (context->has_extension()) { Handle extension = Handle(context->extension(), isolate); @@ -119,7 +119,8 @@ Handle Context::Lookup(Handle name, ContextLookupFlags flags, } } - if (context->is_function_context()) { + // Only functions can have locals, parameters, and a function name. + if (context->IsFunctionContext()) { // we have context-local slots // check non-parameter locals in context @@ -189,9 +190,8 @@ Handle Context::Lookup(Handle name, ContextLookupFlags flags, // proceed with enclosing context if (context->IsGlobalContext()) { follow_context_chain = false; - } else if (context->is_function_context()) { - context = Handle(Context::cast(context->closure()->context()), - isolate); + } else if (context->IsFunctionContext()) { + context = Handle(context->closure()->context(), isolate); } else { context = Handle(context->previous(), isolate); } @@ -212,11 +212,12 @@ bool Context::GlobalIfNotShadowedByEval(Handle name) { // before the global context and check that there are no context // extension objects (conservative check for with statements). while (!context->IsGlobalContext()) { - // Check if the context is a potentially a with context. + // Check if the context is a catch or with context, or has called + // non-strict eval. if (context->has_extension()) return false; // Not a with context so it must be a function context. - ASSERT(context->is_function_context()); + ASSERT(context->IsFunctionContext()); // Check non-parameter locals. Handle scope_info( diff --git a/src/contexts.h b/src/contexts.h index a89e262..64bfc4c 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -289,8 +289,17 @@ class Context: public FixedArray { // Compute the global context by traversing the context chain. Context* global_context(); - // Tells if this is a function context (as opposed to a 'with' context). - bool is_function_context() { return unchecked_previous() == NULL; } + // Predicates for context types. IsGlobalContext is defined on Object + // because we frequently have to know if arbitrary objects are global + // contexts. + bool IsFunctionContext() { + Map* map = this->map(); + return map == map->GetHeap()->function_context_map(); + } + bool IsCatchContext() { + Map* map = this->map(); + return map == map->GetHeap()->catch_context_map(); + } // Tells whether the global context is marked with out of memory. inline bool has_out_of_memory(); diff --git a/src/factory.cc b/src/factory.cc index c7bdef7..ebe57c0 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -249,14 +249,20 @@ Handle Factory::NewFunctionContext(int length, } +Handle Factory::NewCatchContext(Handle previous, + Handle extension) { + CALL_HEAP_FUNCTION( + isolate(), + isolate()->heap()->AllocateCatchContext(*previous, *extension), + Context); +} + + Handle Factory::NewWithContext(Handle previous, - Handle extension, - bool is_catch_context) { + Handle extension) { CALL_HEAP_FUNCTION( isolate(), - isolate()->heap()->AllocateWithContext(*previous, - *extension, - is_catch_context), + isolate()->heap()->AllocateWithContext(*previous, *extension), Context); } diff --git a/src/factory.h b/src/factory.h index 5ea7e33..19dc7cf 100644 --- a/src/factory.h +++ b/src/factory.h @@ -149,10 +149,13 @@ class Factory { Handle NewFunctionContext(int length, Handle closure); + // Create a catch context. + Handle NewCatchContext(Handle previous, + Handle extension); + // Create a 'with' context. Handle NewWithContext(Handle previous, - Handle extension, - bool is_catch_context); + Handle extension); // Return the Symbol matching the passed in string. Handle SymbolFromString(Handle value); diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 972bdf0..e8f214c 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -90,14 +90,14 @@ void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { } -void BreakableStatementChecker::VisitWithEnterStatement( - WithEnterStatement* stmt) { +void BreakableStatementChecker::VisitEnterWithContextStatement( + EnterWithContextStatement* stmt) { Visit(stmt->expression()); } -void BreakableStatementChecker::VisitWithExitStatement( - WithExitStatement* stmt) { +void BreakableStatementChecker::VisitExitContextStatement( + ExitContextStatement* stmt) { } @@ -952,18 +952,19 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { } -void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { - Comment cmnt(masm_, "[ WithEnterStatement"); +void FullCodeGenerator::VisitEnterWithContextStatement( + EnterWithContextStatement* stmt) { + Comment cmnt(masm_, "[ EnterWithContextStatement"); SetStatementPosition(stmt); VisitForStackValue(stmt->expression()); - __ CallRuntime(Runtime::kPushContext, 1); + __ CallRuntime(Runtime::kPushWithContext, 1); StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); } -void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { - Comment cmnt(masm_, "[ WithExitStatement"); +void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) { + Comment cmnt(masm_, "[ ExitContextStatement"); SetStatementPosition(stmt); // Pop context. diff --git a/src/heap.cc b/src/heap.cc index e047c96..533e05d 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -1894,7 +1894,7 @@ bool Heap::CreateInitialMaps() { AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); if (!maybe_obj->ToObject(&obj)) return false; } - set_context_map(Map::cast(obj)); + set_function_context_map(Map::cast(obj)); { MaybeObject* maybe_obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); @@ -1906,6 +1906,12 @@ bool Heap::CreateInitialMaps() { AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); if (!maybe_obj->ToObject(&obj)) return false; } + set_with_context_map(Map::cast(obj)); + + { MaybeObject* maybe_obj = + AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } Map* global_context_map = Map::cast(obj); global_context_map->set_visitor_id(StaticVisitorBase::kVisitGlobalContext); set_global_context_map(global_context_map); @@ -3919,38 +3925,47 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { if (!maybe_result->ToObject(&result)) return maybe_result; } Context* context = reinterpret_cast(result); - context->set_map(context_map()); + context->set_map(function_context_map()); context->set_closure(function); context->set_fcontext(context); context->set_previous(NULL); context->set_extension(NULL); context->set_global(function->context()->global()); - ASSERT(!context->IsGlobalContext()); - ASSERT(context->is_function_context()); - ASSERT(result->IsContext()); - return result; + return context; +} + + +MaybeObject* Heap::AllocateCatchContext(Context* previous, + JSObject* extension) { + Object* result; + { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); + if (!maybe_result->ToObject(&result)) return maybe_result; + } + Context* context = reinterpret_cast(result); + context->set_map(catch_context_map()); + context->set_closure(previous->closure()); + context->set_fcontext(previous->fcontext()); + context->set_previous(previous); + context->set_extension(extension); + context->set_global(previous->global()); + return context; } MaybeObject* Heap::AllocateWithContext(Context* previous, - JSObject* extension, - bool is_catch_context) { + JSObject* extension) { Object* result; { MaybeObject* maybe_result = AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); if (!maybe_result->ToObject(&result)) return maybe_result; } Context* context = reinterpret_cast(result); - context->set_map(is_catch_context ? catch_context_map() : - context_map()); + context->set_map(with_context_map()); context->set_closure(previous->closure()); context->set_fcontext(previous->fcontext()); context->set_previous(previous); context->set_extension(extension); context->set_global(previous->global()); - ASSERT(!context->IsGlobalContext()); - ASSERT(!context->is_function_context()); - ASSERT(result->IsContext()); - return result; + return context; } diff --git a/src/heap.h b/src/heap.h index 664cce8..47b6ab7 100644 --- a/src/heap.h +++ b/src/heap.h @@ -107,8 +107,9 @@ inline Heap* _inline_get_heap_(); V(Map, external_unsigned_int_array_map, ExternalUnsignedIntArrayMap) \ V(Map, external_float_array_map, ExternalFloatArrayMap) \ V(Map, external_double_array_map, ExternalDoubleArrayMap) \ - V(Map, context_map, ContextMap) \ + V(Map, function_context_map, FunctionContextMap) \ V(Map, catch_context_map, CatchContextMap) \ + V(Map, with_context_map, WithContextMap) \ V(Map, code_map, CodeMap) \ V(Map, oddball_map, OddballMap) \ V(Map, global_property_cell_map, GlobalPropertyCellMap) \ @@ -645,10 +646,12 @@ class Heap { MUST_USE_RESULT MaybeObject* AllocateFunctionContext(int length, JSFunction* closure); + // Allocate a catch context. + MUST_USE_RESULT MaybeObject* AllocateCatchContext(Context* previous, + JSObject* extension); // Allocate a 'with' context. MUST_USE_RESULT MaybeObject* AllocateWithContext(Context* previous, - JSObject* extension, - bool is_catch_context); + JSObject* extension); // Allocates a new utility object in the old generation. MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 4288ad5..1d9a0ce 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -2551,19 +2551,20 @@ void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { } -void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { +void HGraphBuilder::VisitEnterWithContextStatement( + EnterWithContextStatement* stmt) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); - return Bailout("WithEnterStatement"); + return Bailout("EnterWithContextStatement"); } -void HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { +void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) { ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); - return Bailout("WithExitStatement"); + return Bailout("ExitContextStatement"); } diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index dc5a9cb..459ef15 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -129,7 +129,8 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Setup the object header. Factory* factory = masm->isolate()->factory(); - __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->context_map()); + __ mov(FieldOperand(eax, HeapObject::kMapOffset), + factory->function_context_map()); __ mov(FieldOperand(eax, Context::kLengthOffset), Immediate(Smi::FromInt(length))); @@ -159,7 +160,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Need to collect. Call into runtime system. __ bind(&gc); - __ TailCallRuntime(Runtime::kNewContext, 1, 1); + __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1); } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index d13edcf..c727c03 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -175,7 +175,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { FastNewContextStub stub(heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } function_in_register = false; // Context is returned in both eax and esi. It replaces the context diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 1781fa5..e0c3ae3 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -184,7 +184,7 @@ bool LCodeGen::GeneratePrologue() { FastNewContextStub stub(heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } RecordSafepoint(Safepoint::kNoDeoptimizationIndex); // Context is returned in both eax and esi. It replaces the context diff --git a/src/mark-compact.cc b/src/mark-compact.cc index e19d891..06df3fc 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -672,8 +672,9 @@ class StaticMarkingVisitor : public StaticVisitorBase { Map* map = SafeMap(ctx); Heap* heap = map->heap(); - if (!(map == heap->raw_unchecked_context_map() || + if (!(map == heap->raw_unchecked_function_context_map() || map == heap->raw_unchecked_catch_context_map() || + map == heap->raw_unchecked_with_context_map() || map == heap->raw_unchecked_global_context_map())) { return false; } diff --git a/src/objects-inl.h b/src/objects-inl.h index f03021e..90dfde6 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -534,22 +534,17 @@ bool Object::IsDeoptimizationOutputData() { bool Object::IsContext() { if (Object::IsHeapObject()) { - Heap* heap = HeapObject::cast(this)->GetHeap(); - return (HeapObject::cast(this)->map() == heap->context_map() || - HeapObject::cast(this)->map() == heap->catch_context_map() || - HeapObject::cast(this)->map() == heap->global_context_map()); + Map* map = HeapObject::cast(this)->map(); + Heap* heap = map->GetHeap(); + return (map == heap->function_context_map() || + map == heap->catch_context_map() || + map == heap->with_context_map() || + map == heap->global_context_map()); } return false; } -bool Object::IsCatchContext() { - return Object::IsHeapObject() && - HeapObject::cast(this)->map() == - HeapObject::cast(this)->GetHeap()->catch_context_map(); -} - - bool Object::IsGlobalContext() { return Object::IsHeapObject() && HeapObject::cast(this)->map() == diff --git a/src/objects.h b/src/objects.h index 5583abd..5330a95 100644 --- a/src/objects.h +++ b/src/objects.h @@ -735,7 +735,6 @@ class MaybeObject BASE_EMBEDDED { V(FixedArray) \ V(FixedDoubleArray) \ V(Context) \ - V(CatchContext) \ V(GlobalContext) \ V(JSFunction) \ V(Code) \ diff --git a/src/parser.cc b/src/parser.cc index 9d6daa4..69e71b8 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -1922,7 +1922,7 @@ Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) { Block* result = new(zone()) Block(NULL, 2, false); if (result != NULL) { - result->AddStatement(new(zone()) WithEnterStatement(obj)); + result->AddStatement(new(zone()) EnterWithContextStatement(obj)); // Create body block. Block* body = new(zone()) Block(NULL, 1, false); @@ -1930,7 +1930,7 @@ Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) { // Create exit block. Block* exit = new(zone()) Block(NULL, 1, false); - exit->AddStatement(new(zone()) WithExitStatement()); + exit->AddStatement(new(zone()) ExitContextStatement()); // Return a try-finally statement. TryFinallyStatement* wrapper = new(zone()) TryFinallyStatement(body, exit); @@ -2089,8 +2089,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { Expect(Token::RPAREN, CHECK_OK); if (peek() == Token::LBRACE) { - // Rewrite the catch body B to a single statement block - // { try B finally { PopContext }}. + // Rewrite the catch body B to a single statement block + // { try B finally { PopContext }}. Block* inner_body; // We need to collect escapes from the body for both the inner // try/finally used to pop the catch context and any possible outer @@ -2107,7 +2107,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { // Create exit block. Block* inner_finally = new(zone()) Block(NULL, 1, false); - inner_finally->AddStatement(new(zone()) WithExitStatement()); + inner_finally->AddStatement(new(zone()) ExitContextStatement()); // Create a try/finally statement. TryFinallyStatement* inner_try_finally = diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc index 0149ed5..bc4125c 100644 --- a/src/prettyprinter.cc +++ b/src/prettyprinter.cc @@ -123,15 +123,16 @@ void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) { } -void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) { - Print(" ("); +void PrettyPrinter::VisitEnterWithContextStatement( + EnterWithContextStatement* node) { + Print(" ("); Visit(node->expression()); Print(") "); } -void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) { - Print(""); +void PrettyPrinter::VisitExitContextStatement(ExitContextStatement* node) { + Print(""); } @@ -797,13 +798,14 @@ void AstPrinter::VisitReturnStatement(ReturnStatement* node) { } -void AstPrinter::VisitWithEnterStatement(WithEnterStatement* node) { - PrintIndentedVisit("WITH ENTER", node->expression()); +void AstPrinter::VisitEnterWithContextStatement( + EnterWithContextStatement* node) { + PrintIndentedVisit("ENTER WITH CONTEXT", node->expression()); } -void AstPrinter::VisitWithExitStatement(WithExitStatement* node) { - PrintIndented("WITH EXIT\n"); +void AstPrinter::VisitExitContextStatement(ExitContextStatement* node) { + PrintIndented("EXIT CONTEXT\n"); } @@ -1191,14 +1193,15 @@ void JsonAstBuilder::VisitReturnStatement(ReturnStatement* stmt) { } -void JsonAstBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { - TagScope tag(this, "WithEnterStatement"); +void JsonAstBuilder::VisitEnterWithContextStatement( + EnterWithContextStatement* stmt) { + TagScope tag(this, "EnterWithContextStatement"); Visit(stmt->expression()); } -void JsonAstBuilder::VisitWithExitStatement(WithExitStatement* stmt) { - TagScope tag(this, "WithExitStatement"); +void JsonAstBuilder::VisitExitContextStatement(ExitContextStatement* stmt) { + TagScope tag(this, "ExitContextStatement"); } diff --git a/src/rewriter.cc b/src/rewriter.cc index 7ed19d5..aa274d4 100644 --- a/src/rewriter.cc +++ b/src/rewriter.cc @@ -197,131 +197,18 @@ void Processor::VisitBreakStatement(BreakStatement* node) { void Processor::VisitDeclaration(Declaration* node) {} void Processor::VisitEmptyStatement(EmptyStatement* node) {} void Processor::VisitReturnStatement(ReturnStatement* node) {} -void Processor::VisitWithEnterStatement(WithEnterStatement* node) {} -void Processor::VisitWithExitStatement(WithExitStatement* node) {} +void Processor::VisitEnterWithContextStatement( + EnterWithContextStatement* node) { +} +void Processor::VisitExitContextStatement(ExitContextStatement* node) {} void Processor::VisitDebuggerStatement(DebuggerStatement* node) {} // Expressions are never visited yet. -void Processor::VisitFunctionLiteral(FunctionLiteral* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitSharedFunctionInfoLiteral( - SharedFunctionInfoLiteral* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitConditional(Conditional* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitVariableProxy(VariableProxy* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitLiteral(Literal* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitRegExpLiteral(RegExpLiteral* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitArrayLiteral(ArrayLiteral* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitObjectLiteral(ObjectLiteral* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitAssignment(Assignment* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitThrow(Throw* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitProperty(Property* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitCall(Call* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitCallNew(CallNew* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitCallRuntime(CallRuntime* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitUnaryOperation(UnaryOperation* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitCountOperation(CountOperation* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitBinaryOperation(BinaryOperation* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitCompareOperation(CompareOperation* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitCompareToNull(CompareToNull* node) { - USE(node); - UNREACHABLE(); -} - - -void Processor::VisitThisFunction(ThisFunction* node) { - USE(node); - UNREACHABLE(); -} +#define DEF_VISIT(type) \ + void Processor::Visit##type(type* expr) { UNREACHABLE(); } +EXPRESSION_NODE_LIST(DEF_VISIT) +#undef DEF_VISIT // Assumes code has been parsed and scopes have been analyzed. Mutates the diff --git a/src/runtime.cc b/src/runtime.cc index 43d3451..7e9c02c 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -7883,7 +7883,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) { +RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -7901,50 +7901,50 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) { } -MUST_USE_RESULT static MaybeObject* PushContextHelper(Isolate* isolate, - Object* object, - bool is_catch_context) { - // Convert the object to a proper JavaScript object. - Object* js_object = object; - if (!js_object->IsJSObject()) { - MaybeObject* maybe_js_object = js_object->ToObject(); - if (!maybe_js_object->ToObject(&js_object)) { - if (!Failure::cast(maybe_js_object)->IsInternalError()) { +RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) { + NoHandleAllocation ha; + ASSERT(args.length() == 1); + JSObject* extension_object; + if (args[0]->IsJSObject()) { + extension_object = JSObject::cast(args[0]); + } else { + // Convert the object to a proper JavaScript object. + MaybeObject* maybe_js_object = args[0]->ToObject(); + if (!maybe_js_object->To(&extension_object)) { + if (Failure::cast(maybe_js_object)->IsInternalError()) { + HandleScope scope(isolate); + Handle handle = args.at(0); + Handle result = + isolate->factory()->NewTypeError("with_expression", + HandleVector(&handle, 1)); + return isolate->Throw(*result); + } else { return maybe_js_object; } - HandleScope scope(isolate); - Handle handle(object, isolate); - Handle result = - isolate->factory()->NewTypeError("with_expression", - HandleVector(&handle, 1)); - return isolate->Throw(*result); } } - Object* result; - { MaybeObject* maybe_result = isolate->heap()->AllocateWithContext( - isolate->context(), JSObject::cast(js_object), is_catch_context); - if (!maybe_result->ToObject(&result)) return maybe_result; - } - - Context* context = Context::cast(result); + Context* context; + MaybeObject* maybe_context = + isolate->heap()->AllocateWithContext(isolate->context(), + extension_object); + if (!maybe_context->To(&context)) return maybe_context; isolate->set_context(context); - - return result; -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_PushContext) { - NoHandleAllocation ha; - ASSERT(args.length() == 1); - return PushContextHelper(isolate, args[0], false); + return context; } RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) { NoHandleAllocation ha; ASSERT(args.length() == 1); - return PushContextHelper(isolate, args[0], true); + JSObject* extension_object = JSObject::cast(args[0]); + Context* context; + MaybeObject* maybe_context = + isolate->heap()->AllocateCatchContext(isolate->context(), + extension_object); + if (!maybe_context->To(&context)) return maybe_context; + isolate->set_context(context); + return context; } @@ -8607,9 +8607,8 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { // Stop search when eval is found or when the global context is // reached. if (attributes != ABSENT || context->IsGlobalContext()) break; - if (context->is_function_context()) { - context = Handle(Context::cast(context->closure()->context()), - isolate); + if (context->IsFunctionContext()) { + context = Handle(context->closure()->context(), isolate); } else { context = Handle(context->previous(), isolate); } @@ -9842,8 +9841,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { Handle scope_info(function->shared()->scope_info()); ScopeInfo<> info(*scope_info); - // Get the context. - Handle context(Context::cast(it.frame()->context())); + // Get the nearest enclosing function context. + Handle context(Context::cast(it.frame()->context())->fcontext()); // Get the locals names and values into a temporary array. // @@ -9859,25 +9858,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { } // Fill in the values of the locals. - for (int i = 0; i < info.NumberOfLocals(); i++) { - if (is_optimized_frame) { - // If we are inspecting an optimized frame use undefined as the - // value for all locals. - // - // TODO(1140): We should be able to get the correct values - // for locals in optimized frames. + if (is_optimized_frame) { + // If we are inspecting an optimized frame use undefined as the + // value for all locals. + // + // TODO(1140): We should be able to get the correct values + // for locals in optimized frames. + for (int i = 0; i < info.NumberOfLocals(); i++) { locals->set(i * 2 + 1, isolate->heap()->undefined_value()); - } else if (i < info.number_of_stack_slots()) { + } + } else { + for (int i = 0; i < info.number_of_stack_slots(); i++) { // Get the value from the stack. locals->set(i * 2 + 1, it.frame()->GetExpression(i)); - } else { - // Traverse the context chain to the function context as all local - // variables stored in the context will be on the function context. + } + for (int i = info.number_of_stack_slots(); i < info.NumberOfLocals(); i++) { Handle name = info.LocalName(i); - while (!context->is_function_context()) { - context = Handle(context->previous()); - } - ASSERT(context->is_function_context()); locals->set(i * 2 + 1, context->get(scope_info->ContextSlotIndex(*name, NULL))); } @@ -10139,7 +10135,7 @@ static Handle MaterializeLocalScope(Isolate* isolate, // context. static Handle MaterializeClosure(Isolate* isolate, Handle context) { - ASSERT(context->is_function_context()); + ASSERT(context->IsFunctionContext()); Handle shared(context->closure()->shared()); Handle serialized_scope_info(shared->scope_info()); @@ -10238,7 +10234,7 @@ class ScopeIterator { int index = function_->shared()->scope_info()-> StackSlotIndex(isolate_->heap()->result_symbol()); at_local_ = index < 0; - } else if (context_->is_function_context()) { + } else if (context_->IsFunctionContext()) { at_local_ = true; } else if (context_->closure() != *function_) { // The context_ is a with block from the outer function. @@ -10272,8 +10268,8 @@ class ScopeIterator { } // Move to the next context. - if (context_->is_function_context()) { - context_ = Handle(Context::cast(context_->closure()->context())); + if (context_->IsFunctionContext()) { + context_ = Handle(context_->closure()->context()); } else { context_ = Handle(context_->previous()); } @@ -10281,7 +10277,7 @@ class ScopeIterator { // If passing the local scope indicate that the current scope is now the // local scope. if (!local_done_ && - (context_->IsGlobalContext() || (context_->is_function_context()))) { + (context_->IsGlobalContext() || context_->IsFunctionContext())) { at_local_ = true; } } @@ -10295,7 +10291,7 @@ class ScopeIterator { ASSERT(context_->global()->IsGlobalObject()); return ScopeTypeGlobal; } - if (context_->is_function_context()) { + if (context_->IsFunctionContext()) { return ScopeTypeClosure; } ASSERT(context_->has_extension()); @@ -10863,19 +10859,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) { // Creates a copy of the with context chain. The copy of the context chain is // is linked to the function context supplied. -static Handle CopyWithContextChain(Handle context_chain, - Handle function_context) { - // At the bottom of the chain. Return the function context to link to. - if (context_chain->is_function_context()) { - return function_context; +static Handle CopyWithContextChain(Isolate* isolate, + Handle current, + Handle base) { + // At the end of the chain. Return the base context to link to. + if (current->IsFunctionContext() || current->IsGlobalContext()) { + return base; } - // Recursively copy the with contexts. - Handle previous(context_chain->previous()); - Handle extension(JSObject::cast(context_chain->extension())); - Handle context = CopyWithContextChain(previous, function_context); - return context->GetIsolate()->factory()->NewWithContext( - context, extension, context_chain->IsCatchContext()); + // Recursively copy the with and catch contexts. + HandleScope scope(isolate); + Handle previous(current->previous()); + Handle new_previous = CopyWithContextChain(isolate, previous, base); + Handle extension(JSObject::cast(current->extension())); + Handle new_current = current->IsCatchContext() + ? isolate->factory()->NewCatchContext(new_previous, extension) + : isolate->factory()->NewWithContext(new_previous, extension); + return scope.CloseAndEscape(new_current); } @@ -11004,11 +11004,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { // Copy any with contexts present and chain them in front of this context. Handle frame_context(Context::cast(frame->context())); Handle function_context(frame_context->fcontext()); - context = CopyWithContextChain(frame_context, context); + context = CopyWithContextChain(isolate, frame_context, context); if (additional_context->IsJSObject()) { - context = isolate->factory()->NewWithContext(context, - Handle::cast(additional_context), false); + Handle extension = Handle::cast(additional_context); + context = isolate->factory()->NewWithContext(context, extension); } // Wrap the evaluation statement in a new function compiled in the newly diff --git a/src/runtime.h b/src/runtime.h index 56d2f14..81ca55e 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -297,8 +297,8 @@ namespace internal { F(PromoteScheduledException, 0, 1) \ \ /* Contexts */ \ - F(NewContext, 1, 1) \ - F(PushContext, 1, 1) \ + F(NewFunctionContext, 1, 1) \ + F(PushWithContext, 1, 1) \ F(PushCatchContext, 1, 1) \ F(DeleteContextSlot, 2, 1) \ F(LoadContextSlot, 2, 2) \ diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 82150c2..35cff70 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -125,7 +125,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { __ movq(rcx, Operand(rsp, 1 * kPointerSize)); // Setup the object header. - __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex); + __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex); __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); @@ -152,7 +152,7 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Need to collect. Call into runtime system. __ bind(&gc); - __ TailCallRuntime(Runtime::kNewContext, 1, 1); + __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1); } diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index e9ce311..f0297a6 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -175,7 +175,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { FastNewContextStub stub(heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } function_in_register = false; // Context is returned in both rax and rsi. It replaces the context diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 79e2b69..e4cd8c3 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -197,7 +197,7 @@ bool LCodeGen::GeneratePrologue() { FastNewContextStub stub(heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); + __ CallRuntime(Runtime::kNewFunctionContext, 1); } RecordSafepoint(Safepoint::kNoDeoptimizationIndex); // Context is returned in both rax and rsi. It replaces the context -- 2.7.4