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:
parent
27c9ef9f79
commit
cd585f26ab
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
||||
|
23
src/heap.cc
23
src/heap.cc
@ -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 =
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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() ==
|
||||
|
@ -809,7 +809,6 @@ class MaybeObject BASE_EMBEDDED {
|
||||
V(FixedDoubleArray) \
|
||||
V(Context) \
|
||||
V(NativeContext) \
|
||||
V(ModuleContext) \
|
||||
V(ScopeInfo) \
|
||||
V(JSFunction) \
|
||||
V(Code) \
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) \
|
||||
|
@ -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:
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user