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
This commit is contained in:
kmillikin@chromium.org 2011-06-09 11:26:01 +00:00
parent 68eab4a8d8
commit 371af773cf
27 changed files with 220 additions and 297 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)
};

View File

@ -96,7 +96,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
PrintF("\n");
}
// check extension/with object
// Check extension/with/global object.
if (context->has_extension()) {
Handle<JSObject> extension = Handle<JSObject>(context->extension(),
isolate);
@ -119,7 +119,8 @@ Handle<Object> Context::Lookup(Handle<String> 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<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
// proceed with enclosing context
if (context->IsGlobalContext()) {
follow_context_chain = false;
} else if (context->is_function_context()) {
context = Handle<Context>(Context::cast(context->closure()->context()),
isolate);
} else if (context->IsFunctionContext()) {
context = Handle<Context>(context->closure()->context(), isolate);
} else {
context = Handle<Context>(context->previous(), isolate);
}
@ -212,11 +212,12 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> 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<SerializedScopeInfo> scope_info(

View File

@ -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();

View File

@ -249,14 +249,20 @@ Handle<Context> Factory::NewFunctionContext(int length,
}
Handle<Context> Factory::NewWithContext(Handle<Context> previous,
Handle<JSObject> extension,
bool is_catch_context) {
Handle<Context> Factory::NewCatchContext(Handle<Context> previous,
Handle<JSObject> extension) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateWithContext(*previous,
*extension,
is_catch_context),
isolate()->heap()->AllocateCatchContext(*previous, *extension),
Context);
}
Handle<Context> Factory::NewWithContext(Handle<Context> previous,
Handle<JSObject> extension) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateWithContext(*previous, *extension),
Context);
}

View File

@ -149,10 +149,13 @@ class Factory {
Handle<Context> NewFunctionContext(int length,
Handle<JSFunction> closure);
// Create a catch context.
Handle<Context> NewCatchContext(Handle<Context> previous,
Handle<JSObject> extension);
// Create a 'with' context.
Handle<Context> NewWithContext(Handle<Context> previous,
Handle<JSObject> extension,
bool is_catch_context);
Handle<JSObject> extension);
// Return the Symbol matching the passed in string.
Handle<String> SymbolFromString(Handle<String> value);

View File

@ -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.

View File

@ -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);
@ -1902,6 +1902,12 @@ bool Heap::CreateInitialMaps() {
}
set_catch_context_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
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;
@ -3919,38 +3925,47 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Context* context = reinterpret_cast<Context*>(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::AllocateWithContext(Context* previous,
JSObject* extension,
bool is_catch_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<Context*>(result);
context->set_map(is_catch_context ? catch_context_map() :
context_map());
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());
ASSERT(!context->IsGlobalContext());
ASSERT(!context->is_function_context());
ASSERT(result->IsContext());
return result;
return context;
}
MaybeObject* Heap::AllocateWithContext(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<Context*>(result);
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());
return context;
}

View File

@ -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);

View File

@ -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");
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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() ==

View File

@ -735,7 +735,6 @@ class MaybeObject BASE_EMBEDDED {
V(FixedArray) \
V(FixedDoubleArray) \
V(Context) \
V(CatchContext) \
V(GlobalContext) \
V(JSFunction) \
V(Code) \

View File

@ -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);
@ -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 =

View File

@ -123,15 +123,16 @@ void PrettyPrinter::VisitReturnStatement(ReturnStatement* node) {
}
void PrettyPrinter::VisitWithEnterStatement(WithEnterStatement* node) {
Print("<enter with> (");
void PrettyPrinter::VisitEnterWithContextStatement(
EnterWithContextStatement* node) {
Print("<enter with context> (");
Visit(node->expression());
Print(") ");
}
void PrettyPrinter::VisitWithExitStatement(WithExitStatement* node) {
Print("<exit with>");
void PrettyPrinter::VisitExitContextStatement(ExitContextStatement* node) {
Print("<exit context>");
}
@ -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");
}

View File

@ -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

View File

@ -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) {
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.
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()) {
return maybe_js_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<Object> handle(object, isolate);
Handle<Object> handle = args.at<Object>(0);
Handle<Object> result =
isolate->factory()->NewTypeError("with_expression",
HandleVector(&handle, 1));
return isolate->Throw(*result);
} else {
return maybe_js_object;
}
}
}
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>(Context::cast(context->closure()->context()),
isolate);
if (context->IsFunctionContext()) {
context = Handle<Context>(context->closure()->context(), isolate);
} else {
context = Handle<Context>(context->previous(), isolate);
}
@ -9842,8 +9841,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
ScopeInfo<> info(*scope_info);
// Get the context.
Handle<Context> context(Context::cast(it.frame()->context()));
// Get the nearest enclosing function context.
Handle<Context> 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.
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.
Handle<String> name = info.LocalName(i);
while (!context->is_function_context()) {
context = Handle<Context>(context->previous());
}
ASSERT(context->is_function_context());
for (int i = info.number_of_stack_slots(); i < info.NumberOfLocals(); i++) {
Handle<String> name = info.LocalName(i);
locals->set(i * 2 + 1,
context->get(scope_info->ContextSlotIndex(*name, NULL)));
}
@ -10139,7 +10135,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
// context.
static Handle<JSObject> MaterializeClosure(Isolate* isolate,
Handle<Context> context) {
ASSERT(context->is_function_context());
ASSERT(context->IsFunctionContext());
Handle<SharedFunctionInfo> shared(context->closure()->shared());
Handle<SerializedScopeInfo> 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>(Context::cast(context_->closure()->context()));
if (context_->IsFunctionContext()) {
context_ = Handle<Context>(context_->closure()->context());
} else {
context_ = Handle<Context>(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<Context> CopyWithContextChain(Handle<Context> context_chain,
Handle<Context> 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<Context> CopyWithContextChain(Isolate* isolate,
Handle<Context> current,
Handle<Context> 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<Context> previous(context_chain->previous());
Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
Handle<Context> 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<Context> previous(current->previous());
Handle<Context> new_previous = CopyWithContextChain(isolate, previous, base);
Handle<JSObject> extension(JSObject::cast(current->extension()));
Handle<Context> 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<Context> frame_context(Context::cast(frame->context()));
Handle<Context> 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<JSObject>::cast(additional_context), false);
Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
context = isolate->factory()->NewWithContext(context, extension);
}
// Wrap the evaluation statement in a new function compiled in the newly

View File

@ -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) \

View File

@ -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);
}

View File

@ -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

View File

@ -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