Introduce global contexts to represent lexical global scope(s).

They are yet unused; actual allocation of global lexical bindings in these contexts is implemented in a separate follow-up CL.

R=svenpanne@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/10876067

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12384 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
rossberg@chromium.org 2012-08-27 09:40:26 +00:00
parent 27c9ef9f79
commit cd585f26ab
18 changed files with 117 additions and 44 deletions

View File

@ -3968,7 +3968,7 @@ class Internals {
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
static const int kEmptySymbolRootIndex = 113;
static const int kEmptySymbolRootIndex = 114;
static const int kJSObjectType = 0xaa;
static const int kFirstNonstringType = 0x80;

View File

@ -184,10 +184,13 @@ void FullCodeGenerator::Generate() {
// Possibly allocate a local context.
int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (heap_slots > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is in r1.
// Argument to NewContext is the function, which is still in r1.
Comment cmnt(masm_, "[ Allocate context");
__ push(r1);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {

View File

@ -313,8 +313,8 @@ bool Context::IsBootstrappingOrValidParentContext(
if (Isolate::Current()->bootstrapper()->IsActive()) return true;
if (!object->IsContext()) return false;
Context* context = Context::cast(object);
return context->IsNativeContext() || context->IsModuleContext() ||
!child->IsModuleContext();
return context->IsNativeContext() || context->IsGlobalContext() ||
context->IsModuleContext() || !child->IsModuleContext();
}

View File

@ -190,7 +190,8 @@ enum BindingFlags {
// Dynamically declared variables/functions are also added
// to lazily allocated extension object. Context::Lookup
// searches the extension object for properties.
// For block contexts, contains the respective ScopeInfo.
// For global and block contexts, contains the respective
// ScopeInfo.
// For module contexts, points back to the respective JSModule.
//
// [ global_object ] A pointer to the global object. Provided for quick
@ -363,6 +364,10 @@ class Context: public FixedArray {
Map* map = this->map();
return map == map->GetHeap()->module_context_map();
}
bool IsGlobalContext() {
Map* map = this->map();
return map == map->GetHeap()->global_context_map();
}
// Tells whether the native context is marked with out of memory.
inline bool has_out_of_memory();

View File

@ -292,6 +292,15 @@ Handle<Context> Factory::NewNativeContext() {
}
Handle<Context> Factory::NewGlobalContext(Handle<JSFunction> function,
Handle<ScopeInfo> scope_info) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateGlobalContext(*function, *scope_info),
Context);
}
Handle<Context> Factory::NewModuleContext(Handle<ScopeInfo> scope_info) {
CALL_HEAP_FUNCTION(
isolate(),

View File

@ -162,6 +162,10 @@ class Factory {
// Create a global (but otherwise uninitialized) context.
Handle<Context> NewNativeContext();
// Create a global context.
Handle<Context> NewGlobalContext(Handle<JSFunction> function,
Handle<ScopeInfo> scope_info);
// Create a module context.
Handle<Context> NewModuleContext(Handle<ScopeInfo> scope_info);

View File

@ -2437,6 +2437,12 @@ bool Heap::CreateInitialMaps() {
}
set_module_context_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
set_global_context_map(Map::cast(obj));
{ MaybeObject* maybe_obj =
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
@ -4905,6 +4911,23 @@ MaybeObject* Heap::AllocateNativeContext() {
}
MaybeObject* Heap::AllocateGlobalContext(JSFunction* function,
ScopeInfo* scope_info) {
Object* result;
{ MaybeObject* maybe_result =
AllocateFixedArray(scope_info->ContextLength(), TENURED);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Context* context = reinterpret_cast<Context*>(result);
context->set_map_no_write_barrier(global_context_map());
context->set_closure(function);
context->set_extension(scope_info);
ASSERT(context->IsGlobalContext());
ASSERT(result->IsContext());
return context;
}
MaybeObject* Heap::AllocateModuleContext(ScopeInfo* scope_info) {
Object* result;
{ MaybeObject* maybe_result =

View File

@ -130,6 +130,7 @@ namespace internal {
V(Map, with_context_map, WithContextMap) \
V(Map, block_context_map, BlockContextMap) \
V(Map, module_context_map, ModuleContextMap) \
V(Map, global_context_map, GlobalContextMap) \
V(Map, oddball_map, OddballMap) \
V(Map, message_object_map, JSMessageObjectMap) \
V(Map, foreign_map, ForeignMap) \
@ -826,6 +827,10 @@ class Heap {
// Allocate a native (but otherwise uninitialized) context.
MUST_USE_RESULT MaybeObject* AllocateNativeContext();
// Allocate a global context.
MUST_USE_RESULT MaybeObject* AllocateGlobalContext(JSFunction* function,
ScopeInfo* scope_info);
// Allocate a module context.
MUST_USE_RESULT MaybeObject* AllocateModuleContext(ScopeInfo* scope_info);

View File

@ -178,10 +178,13 @@ void FullCodeGenerator::Generate() {
// Possibly allocate a local context.
int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (heap_slots > 0) {
Comment cmnt(masm_, "[ Allocate local context");
Comment cmnt(masm_, "[ Allocate context");
// Argument to NewContext is the function, which is still in edi.
__ push(edi);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {

View File

@ -192,10 +192,13 @@ void FullCodeGenerator::Generate() {
// Possibly allocate a local context.
int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (heap_slots > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is in a1.
Comment cmnt(masm_, "[ Allocate context");
// Argument to NewContext is the function, which is still in a1.
__ push(a1);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {

View File

@ -382,7 +382,8 @@ void FixedDoubleArray::FixedDoubleArrayVerify() {
void JSModule::JSModuleVerify() {
VerifyObjectField(kContextOffset);
VerifyObjectField(kScopeInfoOffset);
CHECK(context()->IsUndefined() || context()->IsModuleContext());
CHECK(context()->IsUndefined() ||
Context::cast(context())->IsModuleContext());
}

View File

@ -568,17 +568,16 @@ bool Object::IsTypeFeedbackCells() {
bool Object::IsContext() {
if (Object::IsHeapObject()) {
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->native_context_map() ||
map == heap->block_context_map() ||
map == heap->module_context_map());
}
return false;
if (!Object::IsHeapObject()) return false;
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->native_context_map() ||
map == heap->block_context_map() ||
map == heap->module_context_map() ||
map == heap->global_context_map());
}
@ -589,13 +588,6 @@ bool Object::IsNativeContext() {
}
bool Object::IsModuleContext() {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==
HeapObject::cast(this)->GetHeap()->module_context_map();
}
bool Object::IsScopeInfo() {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==

View File

@ -809,7 +809,6 @@ class MaybeObject BASE_EMBEDDED {
V(FixedDoubleArray) \
V(Context) \
V(NativeContext) \
V(ModuleContext) \
V(ScopeInfo) \
V(JSFunction) \
V(Code) \

View File

@ -8738,19 +8738,35 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSFunction, function, 0);
CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
Context* result;
MaybeObject* maybe_result =
isolate->heap()->AllocateGlobalContext(function, scope_info);
if (!maybe_result->To(&result)) return maybe_result;
isolate->set_context(result);
return result; // non-failure
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, function, 0);
int length = function->shared()->scope_info()->ContextLength();
Object* result;
{ MaybeObject* maybe_result =
isolate->heap()->AllocateFunctionContext(length, function);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Context* result;
MaybeObject* maybe_result =
isolate->heap()->AllocateFunctionContext(length, function);
if (!maybe_result->To(&result)) return maybe_result;
isolate->set_context(Context::cast(result));
isolate->set_context(result);
return result; // non-failure
}

View File

@ -330,6 +330,7 @@ namespace internal {
F(PromoteScheduledException, 0, 1) \
\
/* Contexts */ \
F(NewGlobalContext, 2, 1) \
F(NewFunctionContext, 1, 1) \
F(PushWithContext, 2, 1) \
F(PushCatchContext, 3, 1) \

View File

@ -227,6 +227,12 @@ Scope* Scope::DeserializeScopeChain(Context* context, Scope* global_scope,
for (Scope* s = innermost_scope; s != NULL; s = s->outer_scope()) {
s->scope_inside_with_ = true;
}
} else if (context->IsGlobalContext()) {
ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
current_scope = new(zone) Scope(current_scope,
GLOBAL_SCOPE,
Handle<ScopeInfo>(scope_info),
zone);
} else if (context->IsModuleContext()) {
ScopeInfo* scope_info = ScopeInfo::cast(context->module()->scope_info());
current_scope = new(zone) Scope(current_scope,
@ -491,7 +497,7 @@ Variable* Scope::DeclareLocal(Handle<String> name,
}
Variable* Scope::DeclareGlobal(Handle<String> name) {
Variable* Scope::DeclareDynamicGlobal(Handle<String> name) {
ASSERT(is_global_scope());
return variables_.Declare(this,
name,
@ -1047,8 +1053,8 @@ bool Scope::ResolveVariable(CompilationInfo* info,
break;
case UNBOUND:
// No binding has been found. Declare a variable in global scope.
var = info->global_scope()->DeclareGlobal(proxy->name());
// No binding has been found. Declare a variable on the global object.
var = info->global_scope()->DeclareDynamicGlobal(proxy->name());
break;
case UNBOUND_EVAL_SHADOWED:

View File

@ -160,7 +160,7 @@ class Scope: public ZoneObject {
// global scope. The variable was introduced (possibly from an inner
// scope) by a reference to an unresolved variable with no intervening
// with statements or eval calls.
Variable* DeclareGlobal(Handle<String> name);
Variable* DeclareDynamicGlobal(Handle<String> name);
// Create a new unresolved variable.
template<class Visitor>

View File

@ -174,10 +174,13 @@ void FullCodeGenerator::Generate() {
// Possibly allocate a local context.
int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (heap_slots > 0) {
Comment cmnt(masm_, "[ Allocate local context");
Comment cmnt(masm_, "[ Allocate context");
// Argument to NewContext is the function, which is still in rdi.
__ push(rdi);
if (heap_slots <= FastNewContextStub::kMaximumSlots) {
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
__ Push(info->scope()->GetScopeInfo());
__ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(heap_slots);
__ CallStub(&stub);
} else {