if (!frame->is_optimized()) {
// If there is an arguments variable in the stack, we return that.
- Handle<SerializedScopeInfo> info(function->shared()->scope_info());
- int index = info->StackSlotIndex(isolate->heap()->arguments_symbol());
+ Handle<ScopeInfo> scope_info(function->shared()->scope_info());
+ int index = scope_info->StackSlotIndex(
+ isolate->heap()->arguments_symbol());
if (index >= 0) {
Handle<Object> arguments(frame->GetExpression(index), isolate);
if (!arguments->IsArgumentsMarker()) return *arguments;
// the compilation info is set if compilation succeeded.
bool succeeded = MakeCode(info);
if (!info->shared_info().is_null()) {
- Handle<SerializedScopeInfo> scope_info =
- SerializedScopeInfo::Create(info->scope());
+ Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope());
info->shared_info()->set_scope_info(*scope_info);
}
return succeeded;
lit->name(),
lit->materialized_literal_count(),
info->code(),
- SerializedScopeInfo::Create(info->scope()));
+ ScopeInfo::Create(info->scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script);
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
if (info->IsOptimizing()) {
- ASSERT(shared->scope_info() != SerializedScopeInfo::Empty());
+ ASSERT(shared->scope_info() != ScopeInfo::Empty());
function->ReplaceCode(*code);
} else {
// Update the shared function info with the compiled code and the
// info initialization is important since set_scope_info might
// trigger a GC, causing the ASSERT below to be invalid if the code
// was flushed. By settting the code object last we avoid this.
- Handle<SerializedScopeInfo> scope_info =
- SerializedScopeInfo::Create(info->scope());
+ Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope());
shared->set_scope_info(*scope_info);
shared->set_code(*code);
if (!function.is_null()) {
bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive(info.isolate());
- Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
+ Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
// Generate code
if (FLAG_lazy && allow_lazy) {
} else if ((V8::UseCrankshaft() && MakeCrankshaftCode(&info)) ||
(!V8::UseCrankshaft() && FullCodeGenerator::MakeCode(&info))) {
ASSERT(!info.code().is_null());
- scope_info = SerializedScopeInfo::Create(info.scope());
+ scope_info = ScopeInfo::Create(info.scope());
} else {
return Handle<SharedFunctionInfo>::null();
}
if (context->IsFunctionContext() || context->IsBlockContext()) {
// Use serialized scope information of functions and blocks to search
// for the context index.
- Handle<SerializedScopeInfo> scope_info;
+ Handle<ScopeInfo> scope_info;
if (context->IsFunctionContext()) {
- scope_info = Handle<SerializedScopeInfo>(
+ scope_info = Handle<ScopeInfo>(
context->closure()->shared()->scope_info(), isolate);
} else {
- scope_info = Handle<SerializedScopeInfo>(
- SerializedScopeInfo::cast(context->extension()), isolate);
+ scope_info = Handle<ScopeInfo>(
+ ScopeInfo::cast(context->extension()), isolate);
}
VariableMode mode;
int slot_index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(context->IsFunctionContext());
// Check non-parameter locals.
- Handle<SerializedScopeInfo> scope_info(
- context->closure()->shared()->scope_info());
+ Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info());
VariableMode mode;
int index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (param_index >= 0) return false;
// Check context only holding the function name variable.
- index = scope_info->FunctionContextSlotIndex(*name, NULL);
+ index = scope_info->FunctionContextSlotIndex(*name, &mode);
if (index >= 0) return false;
context = context->previous();
}
Context* context = this;
while (!context->IsGlobalContext()) {
if (context->IsFunctionContext()) {
- Handle<SerializedScopeInfo> scope_info(
- context->closure()->shared()->scope_info());
- if (scope_info->CallsEval() && !scope_info->IsStrictMode()) {
+ if (context->closure()->shared()->scope_info()->CallsNonStrictEval()) {
// No need to go further since the answers will not change from
// here.
*outer_scope_calls_non_strict_eval = true;
Handle<Context> Factory::NewBlockContext(
Handle<JSFunction> function,
Handle<Context> previous,
- Handle<SerializedScopeInfo> scope_info) {
+ Handle<ScopeInfo> scope_info) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateBlockContext(*function,
}
-Handle<SerializedScopeInfo> Factory::NewSerializedScopeInfo(int length) {
+Handle<ScopeInfo> Factory::NewScopeInfo(int length) {
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->AllocateSerializedScopeInfo(length),
- SerializedScopeInfo);
+ isolate()->heap()->AllocateScopeInfo(length),
+ ScopeInfo);
}
Handle<String> name,
int number_of_literals,
Handle<Code> code,
- Handle<SerializedScopeInfo> scope_info) {
+ Handle<ScopeInfo> scope_info) {
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
shared->set_code(*code);
shared->set_scope_info(*scope_info);
// Create a 'block' context.
Handle<Context> NewBlockContext(Handle<JSFunction> function,
Handle<Context> previous,
- Handle<SerializedScopeInfo> scope_info);
+ Handle<ScopeInfo> scope_info);
// Return the Symbol matching the passed in string.
Handle<String> SymbolFromString(Handle<String> value);
Handle<Context> context,
PretenureFlag pretenure = TENURED);
- Handle<SerializedScopeInfo> NewSerializedScopeInfo(int length);
+ Handle<ScopeInfo> NewScopeInfo(int length);
Handle<Code> NewCode(const CodeDesc& desc,
Code::Flags flags,
Handle<String> name,
int number_of_literals,
Handle<Code> code,
- Handle<SerializedScopeInfo> scope_info);
+ Handle<ScopeInfo> scope_info);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
Handle<JSMessageObject> NewJSMessageObject(
if (IsConstructor()) accumulator->Add("new ");
accumulator->PrintFunction(function, receiver, &code);
- Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
+ // Get scope information for nicer output, if possible. If code is NULL, or
+ // doesn't contain scope info, scope_info will return 0 for the number of
+ // parameters, stack local variables, context local variables, stack slots,
+ // or context slots.
+ Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
if (function->IsJSFunction()) {
Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
- scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
+ scope_info = Handle<ScopeInfo>(shared->scope_info());
Object* script_obj = shared->script();
if (script_obj->IsScript()) {
Handle<Script> script(Script::cast(script_obj));
accumulator->Add("(this=%o", receiver);
- // Get scope information for nicer output, if possible. If code is
- // NULL, or doesn't contain scope info, info will return 0 for the
- // number of parameters, stack slots, or context slots.
- ScopeInfo<PreallocatedStorage> info(*scope_info);
-
// Print the parameters.
int parameters_count = ComputeParametersCount();
for (int i = 0; i < parameters_count; i++) {
// If we have a name for the parameter we print it. Nameless
// parameters are either because we have more actual parameters
// than formal parameters or because we have no scope information.
- if (i < info.number_of_parameters()) {
- accumulator->PrintName(*info.parameter_name(i));
+ if (i < scope_info->ParameterCount()) {
+ accumulator->PrintName(scope_info->ParameterName(i));
accumulator->Add("=");
}
accumulator->Add("%o", GetParameter(i));
accumulator->Add(" {\n");
// Compute the number of locals and expression stack elements.
- int stack_locals_count = info.number_of_stack_slots();
- int heap_locals_count = info.number_of_context_slots();
+ int stack_locals_count = scope_info->StackLocalCount();
+ int heap_locals_count = scope_info->ContextLocalCount();
int expressions_count = ComputeExpressionsCount();
// Print stack-allocated local variables.
}
for (int i = 0; i < stack_locals_count; i++) {
accumulator->Add(" var ");
- accumulator->PrintName(*info.stack_slot_name(i));
+ accumulator->PrintName(scope_info->StackLocalName(i));
accumulator->Add(" = ");
if (i < expressions_count) {
accumulator->Add("%o", GetExpression(i));
}
// Print heap-allocated local variables.
- if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
+ if (heap_locals_count > 0) {
accumulator->Add(" // heap-allocated locals\n");
}
- for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
+ for (int i = 0; i < heap_locals_count; i++) {
accumulator->Add(" var ");
- accumulator->PrintName(*info.context_slot_name(i));
+ accumulator->PrintName(scope_info->ContextLocalName(i));
accumulator->Add(" = ");
if (context != NULL) {
if (i < context->length()) {
- accumulator->Add("%o", context->get(i));
+ accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
} else {
accumulator->Add(
"// warning: missing context slot - inconsistent frame?");
if (stmt->block_scope() != NULL) {
{ Comment cmnt(masm_, "[ Extend block context");
scope_ = stmt->block_scope();
- Handle<SerializedScopeInfo> scope_info = scope_->GetSerializedScopeInfo();
- int heap_slots =
- scope_info->NumberOfContextSlots() - Context::MIN_CONTEXT_SLOTS;
+ Handle<ScopeInfo> scope_info = scope_->GetScopeInfo();
+ int heap_slots = scope_info->ContextLength() - Context::MIN_CONTEXT_SLOTS;
__ Push(scope_info);
PushFunctionArgumentForContextAllocation();
if (heap_slots <= FastNewBlockContextStub::kMaximumSlots) {
int context_slots = scope_info.number_of_context_slots();
// The real slot ID is internal_slots + context_slot_id.
int internal_slots = Context::MIN_CONTEXT_SLOTS;
- int locals = scope_info.NumberOfLocals();
+ int locals = scope_info.LocalCount();
int current_abbreviation = 4;
for (int param = 0; param < params; ++param) {
w->WriteULEB128(current_abbreviation++);
w->WriteString(
- *scope_info.parameter_name(param)->ToCString(DISALLOW_NULLS));
+ *scope_info.ParameterName(param)->ToCString(DISALLOW_NULLS));
w->Write<uint32_t>(ty_offset);
Writer::Slot<uint32_t> block_size = w->CreateSlotHere<uint32_t>();
uintptr_t block_start = w->position();
int context_slots = scope_info.number_of_context_slots();
// The real slot ID is internal_slots + context_slot_id.
int internal_slots = Context::MIN_CONTEXT_SLOTS;
- int locals = scope_info.NumberOfLocals();
+ int locals = scope_info.LocalCount();
int total_children =
params + slots + context_slots + internal_slots + locals + 2;
AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel);
if (!maybe_obj->ToObject(&obj)) return false;
}
- set_serialized_scope_info_map(Map::cast(obj));
+ set_scope_info_map(Map::cast(obj));
{ MaybeObject* maybe_obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize);
if (!maybe_obj->ToObject(&obj)) return false;
share->set_name(name);
Code* illegal = isolate_->builtins()->builtin(Builtins::kIllegal);
share->set_code(illegal);
- share->set_scope_info(SerializedScopeInfo::Empty());
+ share->set_scope_info(ScopeInfo::Empty());
Code* construct_stub =
isolate_->builtins()->builtin(Builtins::kJSConstructStubGeneric);
share->set_construct_stub(construct_stub);
MaybeObject* Heap::AllocateBlockContext(JSFunction* function,
Context* previous,
- SerializedScopeInfo* scope_info) {
+ ScopeInfo* scope_info) {
Object* result;
{ MaybeObject* maybe_result =
- AllocateFixedArrayWithHoles(scope_info->NumberOfContextSlots());
+ AllocateFixedArrayWithHoles(scope_info->ContextLength());
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Context* context = reinterpret_cast<Context*>(result);
}
-MaybeObject* Heap::AllocateSerializedScopeInfo(int length) {
- Object* result;
- { MaybeObject* maybe_result = AllocateFixedArray(length, TENURED);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- SerializedScopeInfo* scope_info =
- reinterpret_cast<SerializedScopeInfo*>(result);
- scope_info->set_map(serialized_scope_info_map());
+MaybeObject* Heap::AllocateScopeInfo(int length) {
+ FixedArray* scope_info;
+ MaybeObject* maybe_scope_info = AllocateFixedArray(length, TENURED);
+ if (!maybe_scope_info->To(&scope_info)) return maybe_scope_info;
+ scope_info->set_map(scope_info_map());
return scope_info;
}
V(Map, global_context_map, GlobalContextMap) \
V(Map, fixed_array_map, FixedArrayMap) \
V(Map, code_map, CodeMap) \
- V(Map, serialized_scope_info_map, SerializedScopeInfoMap) \
+ V(Map, scope_info_map, ScopeInfoMap) \
V(Map, fixed_cow_array_map, FixedCOWArrayMap) \
V(Map, fixed_double_array_map, FixedDoubleArrayMap) \
V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel) \
MUST_USE_RESULT MaybeObject* AllocateCodeCache();
// Allocates a serialized scope info.
- MUST_USE_RESULT MaybeObject* AllocateSerializedScopeInfo(int length);
+ MUST_USE_RESULT MaybeObject* AllocateScopeInfo(int length);
// Allocates an empty PolymorphicCodeCache.
MUST_USE_RESULT MaybeObject* AllocatePolymorphicCodeCache();
// Allocate a block context.
MUST_USE_RESULT MaybeObject* AllocateBlockContext(JSFunction* function,
Context* previous,
- SerializedScopeInfo* info);
+ ScopeInfo* info);
// Allocates a new utility object in the old generation.
MUST_USE_RESULT MaybeObject* AllocateStruct(InstanceType type);
TraceInline(target, caller, "could not generate deoptimization info");
return false;
}
- if (target_shared->scope_info() == SerializedScopeInfo::Empty()) {
+ if (target_shared->scope_info() == ScopeInfo::Empty()) {
// The scope info might not have been set if a lazily compiled
// function is inlined before being called for the first time.
- Handle<SerializedScopeInfo> target_scope_info =
- SerializedScopeInfo::Create(target_info.scope());
+ Handle<ScopeInfo> target_scope_info =
+ ScopeInfo::Create(target_info.scope());
target_shared->set_scope_info(*target_scope_info);
}
target_shared->EnableDeoptimizationSupport(*target_info.code());
ReplaceCodeObject(shared_info->code(), *code);
Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
if (code_scope_info->IsFixedArray()) {
- shared_info->set_scope_info(SerializedScopeInfo::cast(*code_scope_info));
+ shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
}
}
}
-bool Object::IsSerializedScopeInfo() {
+bool Object::IsScopeInfo() {
return Object::IsHeapObject() &&
HeapObject::cast(this)->map() ==
- HeapObject::cast(this)->GetHeap()->serialized_scope_info_map();
+ HeapObject::cast(this)->GetHeap()->scope_info_map();
}
CAST_ACCESSOR(SymbolTable)
CAST_ACCESSOR(JSFunctionResultCache)
CAST_ACCESSOR(NormalizedMapCache)
+CAST_ACCESSOR(ScopeInfo)
CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(CodeCacheHashTable)
CAST_ACCESSOR(PolymorphicCodeCacheHashTable)
}
-SerializedScopeInfo* SharedFunctionInfo::scope_info() {
- return reinterpret_cast<SerializedScopeInfo*>(
- READ_FIELD(this, kScopeInfoOffset));
+ScopeInfo* SharedFunctionInfo::scope_info() {
+ return reinterpret_cast<ScopeInfo*>(READ_FIELD(this, kScopeInfoOffset));
}
-void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
+void SharedFunctionInfo::set_scope_info(ScopeInfo* value,
WriteBarrierMode mode) {
WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
CONDITIONAL_WRITE_BARRIER(GetHeap(),
// - MapCache
// - Context
// - JSFunctionResultCache
-// - SerializedScopeInfo
+// - ScopeInfo
// - FixedDoubleArray
// - ExternalArray
// - ExternalPixelArray
V(FixedDoubleArray) \
V(Context) \
V(GlobalContext) \
- V(SerializedScopeInfo) \
+ V(ScopeInfo) \
V(JSFunction) \
V(Code) \
V(Oddball) \
};
+// ScopeInfo represents information about different scopes of a source
+// program and the allocation of the scope's variables. Scope information
+// is stored in a compressed form in ScopeInfo objects and is used
+// at runtime (stack dumps, deoptimization, etc.).
+
// This object provides quick access to scope info details for runtime
-// routines w/o the need to explicitly create a ScopeInfo object.
-class SerializedScopeInfo : public FixedArray {
- public :
- static SerializedScopeInfo* cast(Object* object) {
- ASSERT(object->IsSerializedScopeInfo());
- return reinterpret_cast<SerializedScopeInfo*>(object);
- }
+// routines.
+class ScopeInfo : public FixedArray {
+ public:
+ static inline ScopeInfo* cast(Object* object);
// Return the type of this scope.
ScopeType Type();
// Is this scope a strict mode scope?
bool IsStrictMode();
- // Return the number of stack slots for code.
- int NumberOfStackSlots();
+ // Does this scope make a non-strict eval call?
+ bool CallsNonStrictEval() {
+ return CallsEval() && !IsStrictMode();
+ }
+
+ // Return the total number of locals allocated on the stack and in the
+ // context. This includes the parameters that are allocated in the context.
+ int LocalCount();
- // Return the number of context slots for code.
- int NumberOfContextSlots();
+ // Return the number of stack slots for code. This number consists of two
+ // parts:
+ // 1. One stack slot per stack allocated local.
+ // 2. One stack slot for the function name if it is stack allocated.
+ int StackSlotCount();
- // Return if this has context slots besides MIN_CONTEXT_SLOTS;
+ // Return the number of context slots for code if a context is allocated. This
+ // number consists of three parts:
+ // 1. Size of fixed header for every context: Context::MIN_CONTEXT_SLOTS
+ // 2. One context slot per context allocated local.
+ // 3. One context slot for the function name if it is context allocated.
+ // Parameters allocated in the context count as context allocated locals. If
+ // no contexts are allocated for this scope ContextLength returns 0.
+ int ContextLength();
+
+ // Is this scope the scope of a named function expression?
+ bool HasFunctionName();
+
+ // Return if this has context allocated locals.
bool HasHeapAllocatedLocals();
// Return if contexts are allocated for this scope.
bool HasContext();
+ // Return the function_name if present.
+ String* FunctionName();
+
+ // Return the name of the given parameter.
+ String* ParameterName(int var);
+
+ // Return the name of the given local.
+ String* LocalName(int var);
+
+ // Return the name of the given stack local.
+ String* StackLocalName(int var);
+
+ // Return the name of the given context local.
+ String* ContextLocalName(int var);
+
+ // Return the mode of the given context local.
+ VariableMode ContextLocalMode(int var);
+
// Lookup support for serialized scope info. Returns the
// the stack slot index for a given slot name if the slot is
// present; otherwise returns a value < 0. The name must be a symbol
// must be a symbol (canonicalized).
int FunctionContextSlotIndex(String* name, VariableMode* mode);
- static Handle<SerializedScopeInfo> Create(Scope* scope);
+ static Handle<ScopeInfo> Create(Scope* scope);
// Serializes empty scope info.
- static SerializedScopeInfo* Empty();
+ static ScopeInfo* Empty();
+
+#ifdef DEBUG
+ void Print();
+#endif
+
+ // The layout of the static part of a ScopeInfo is as follows. Each entry is
+ // numeric and occupies one array slot.
+ // 1. A set of properties of the scope
+ // 2. The number of parameters. This only applies to function scopes. For
+ // non-function scopes this is 0.
+ // 3. The number of non-parameter variables allocated on the stack.
+ // 4. The number of non-parameter and parameter variables allocated in the
+ // context.
+#define FOR_EACH_NUMERIC_FIELD(V) \
+ V(Flags) \
+ V(ParameterCount) \
+ V(StackLocalCount) \
+ V(ContextLocalCount)
+
+#define FIELD_ACCESSORS(name) \
+ void Set##name(int value) { \
+ set(k##name, Smi::FromInt(value)); \
+ } \
+ int name() { \
+ if (length() > 0) { \
+ return Smi::cast(get(k##name))->value(); \
+ } else { \
+ return 0; \
+ } \
+ }
+ FOR_EACH_NUMERIC_FIELD(FIELD_ACCESSORS)
+#undef FIELD_ACCESSORS
private:
- Object** ContextEntriesAddr();
+ enum {
+#define DECL_INDEX(name) k##name,
+ FOR_EACH_NUMERIC_FIELD(DECL_INDEX)
+#undef DECL_INDEX
+#undef FOR_EACH_NUMERIC_FIELD
+ kVariablePartIndex
+ };
- Object** ParameterEntriesAddr();
+ // The layout of the variable part of a ScopeInfo is as follows:
+ // 1. ParameterEntries:
+ // This part stores the names of the parameters for function scopes. One
+ // slot is used per parameter, so in total this part occupies
+ // ParameterCount() slots in the array. For other scopes than function
+ // scopes ParameterCount() is 0.
+ // 2. StackLocalEntries:
+ // Contains the names of local variables that are allocated on the stack,
+ // in increasing order of the stack slot index. One slot is used per stack
+ // local, so in total this part occupies StackLocalCount() slots in the
+ // array.
+ // 3. ContextLocalNameEntries:
+ // Contains the names of local variables and parameters that are allocated
+ // in the context. They are stored in increasing order of the context slot
+ // index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
+ // context local, so in total this part occupies ContextLocalCount() slots
+ // in the array.
+ // 4. ContextLocalModeEntries:
+ // Contains the variable modes corresponding to the context locals in
+ // ContextLocalNameEntries. One slot is used per context local, so in total
+ // this part occupies ContextLocalCount() slots in the array.
+ // 5. FunctionNameEntryIndex:
+ // If the scope belongs to a named function expression this part contains
+ // information about the function variable. It always occupies two array
+ // slots: a. The name of the function variable.
+ // b. The context or stack slot index for the variable.
+ int ParameterEntriesIndex();
+ int StackLocalEntriesIndex();
+ int ContextLocalNameEntriesIndex();
+ int ContextLocalModeEntriesIndex();
+ int FunctionNameEntryIndex();
+
+ // Location of the function variable for named function expressions.
+ enum FunctionVariableInfo {
+ NONE, // No function name present.
+ STACK, // Function
+ CONTEXT,
+ UNUSED
+ };
- Object** StackSlotEntriesAddr();
+ // Properties of scopes.
+ class TypeField: public BitField<ScopeType, 0, 3> {};
+ class CallsEvalField: public BitField<bool, 3, 1> {};
+ class StrictModeField: public BitField<bool, 4, 1> {};
+ class FunctionVariableField: public BitField<FunctionVariableInfo, 5, 2> {};
+ class FunctionVariableMode: public BitField<VariableMode, 7, 3> {};
};
DECL_ACCESSORS(code, Code)
// [scope_info]: Scope info.
- DECL_ACCESSORS(scope_info, SerializedScopeInfo)
+ DECL_ACCESSORS(scope_info, ScopeInfo)
// [construct stub]: Code stub for constructing instances of this function.
DECL_ACCESSORS(construct_stub, Code)
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Handle<SharedFunctionInfo> shared =
isolate()->factory()->NewSharedFunctionInfo(name, literals, code,
- Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
+ Handle<ScopeInfo>(fun->shared()->scope_info()));
shared->set_construct_stub(*construct_stub);
// Copy the function data to the shared function info.
void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
HeapEntry* entry) {
if (js_obj->IsJSFunction()) {
- HandleScope hs;
JSFunction* func = JSFunction::cast(js_obj);
Context* context = func->context();
- ZoneScope zscope(Isolate::Current(), DELETE_ON_EXIT);
- SerializedScopeInfo* serialized_scope_info =
- context->closure()->shared()->scope_info();
- ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info);
- int locals_number = zone_scope_info.NumberOfLocals();
- for (int i = 0; i < locals_number; ++i) {
- String* local_name = *zone_scope_info.LocalName(i);
- int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
- if (idx >= 0 && idx < context->length()) {
- SetClosureReference(js_obj, entry, local_name, context->get(idx));
- }
+ ScopeInfo* scope_info = context->closure()->shared()->scope_info();
+
+ // Add context allocated locals.
+ int context_locals = scope_info->ContextLocalCount();
+ for (int i = 0; i < context_locals; ++i) {
+ String* local_name = scope_info->ContextLocalName(i);
+ int idx = Context::MIN_CONTEXT_SLOTS + i;
+ SetClosureReference(js_obj, entry, local_name, context->get(idx));
+ }
+
+ // Add function variable.
+ if (scope_info->HasFunctionName()) {
+ String* name = scope_info->FunctionName();
+ int idx = Context::MIN_CONTEXT_SLOTS + context_locals;
+#ifdef DEBUG
+ VariableMode mode;
+ ASSERT(idx == scope_info->FunctionContextSlotIndex(name, &mode));
+#endif
+ SetClosureReference(js_obj, entry, name, context->get(idx));
}
}
}
--index;
}
- ScopeInfo<> scope_info(callee->shared()->scope_info());
+ Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
while (index >= 0) {
// Detect duplicate names to the right in the parameter list.
- Handle<String> name = scope_info.parameter_name(index);
- int context_slot_count = scope_info.number_of_context_slots();
+ Handle<String> name(scope_info->ParameterName(index));
+ int context_local_count = scope_info->ContextLocalCount();
bool duplicate = false;
for (int j = index + 1; j < parameter_count; ++j) {
- if (scope_info.parameter_name(j).is_identical_to(name)) {
+ if (scope_info->ParameterName(j) == *name) {
duplicate = true;
break;
}
// The context index goes in the parameter map with a hole in the
// arguments array.
int context_index = -1;
- for (int j = Context::MIN_CONTEXT_SLOTS;
- j < context_slot_count;
- ++j) {
- if (scope_info.context_slot_name(j).is_identical_to(name)) {
+ for (int j = 0; j < context_local_count; ++j) {
+ if (scope_info->ContextLocalName(j) == *name) {
context_index = j;
break;
}
}
ASSERT(context_index >= 0);
arguments->set_the_hole(index);
- parameter_map->set(index + 2, Smi::FromInt(context_index));
+ parameter_map->set(index + 2, Smi::FromInt(
+ Context::MIN_CONTEXT_SLOTS + context_index));
}
--index;
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSFunction, function, args[0]);
- int length = function->shared()->scope_info()->NumberOfContextSlots();
+ int length = function->shared()->scope_info()->ContextLength();
Object* result;
{ MaybeObject* maybe_result =
isolate->heap()->AllocateFunctionContext(length, function);
RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
- SerializedScopeInfo* scope_info = SerializedScopeInfo::cast(args[0]);
+ ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
JSFunction* function;
if (args[1]->IsSmi()) {
// A smi sentinel indicates a context nested inside global code rather
// Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
Handle<SharedFunctionInfo> shared(function->shared());
- Handle<SerializedScopeInfo> scope_info(shared->scope_info());
- ASSERT(*scope_info != SerializedScopeInfo::Empty());
- ScopeInfo<> info(*scope_info);
+ Handle<ScopeInfo> scope_info(shared->scope_info());
+ ASSERT(*scope_info != ScopeInfo::Empty());
// Get the locals names and values into a temporary array.
//
// (e.g. .result)? For users of the debugger, they will probably be
// confusing.
Handle<FixedArray> locals =
- isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2);
+ isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
// Fill in the values of the locals.
int i = 0;
- for (; i < info.number_of_stack_slots(); ++i) {
+ for (; i < scope_info->StackLocalCount(); ++i) {
// Use the value from the stack.
- locals->set(i * 2, *info.LocalName(i));
+ locals->set(i * 2, scope_info->LocalName(i));
locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
}
- if (i < info.NumberOfLocals()) {
+ if (i < scope_info->LocalCount()) {
// Get the context containing declarations.
Handle<Context> context(
Context::cast(it.frame()->context())->declaration_context());
- for (; i < info.NumberOfLocals(); ++i) {
- Handle<String> name = info.LocalName(i);
+ for (; i < scope_info->LocalCount(); ++i) {
+ Handle<String> name(scope_info->LocalName(i));
+ VariableMode mode;
locals->set(i * 2, *name);
locals->set(i * 2 + 1,
- context->get(scope_info->ContextSlotIndex(*name, NULL)));
+ context->get(scope_info->ContextSlotIndex(*name, &mode)));
}
}
// Find the number of arguments to fill. At least fill the number of
// parameters for the function and fill more if more parameters are provided.
- int argument_count = info.number_of_parameters();
+ int argument_count = scope_info->ParameterCount();
if (argument_count < frame_inspector.GetParametersCount()) {
argument_count = frame_inspector.GetParametersCount();
}
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
- 2 * (argument_count + info.NumberOfLocals()) +
+ 2 * (argument_count + scope_info->LocalCount()) +
(at_return ? 1 : 0);
Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
// Add the locals count
details->set(kFrameDetailsLocalCountIndex,
- Smi::FromInt(info.NumberOfLocals()));
+ Smi::FromInt(scope_info->LocalCount()));
// Add the source position.
if (position != RelocInfo::kNoPosition) {
// Add arguments name and value.
for (int i = 0; i < argument_count; i++) {
// Name of the argument.
- if (i < info.number_of_parameters()) {
- details->set(details_index++, *info.parameter_name(i));
+ if (i < scope_info->ParameterCount()) {
+ details->set(details_index++, scope_info->ParameterName(i));
} else {
details->set(details_index++, heap->undefined_value());
}
}
// Add locals name and value from the temporary copy from the function frame.
- for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
+ for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
details->set(details_index++, locals->get(i));
}
// Copy all the context locals into an object used to materialize a scope.
static bool CopyContextLocalsToScopeObject(
Isolate* isolate,
- Handle<SerializedScopeInfo> serialized_scope_info,
- ScopeInfo<>& scope_info,
+ Handle<ScopeInfo> scope_info,
Handle<Context> context,
Handle<JSObject> scope_object) {
// Fill all context locals to the context extension.
- for (int i = Context::MIN_CONTEXT_SLOTS;
- i < scope_info.number_of_context_slots();
- i++) {
- int context_index = serialized_scope_info->ContextSlotIndex(
- *scope_info.context_slot_name(i), NULL);
+ for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
+ VariableMode mode;
+ int context_index = scope_info->ContextSlotIndex(
+ scope_info->ContextLocalName(i), &mode);
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
SetProperty(scope_object,
- scope_info.context_slot_name(i),
+ Handle<String>(scope_info->ContextLocalName(i)),
Handle<Object>(context->get(context_index), isolate),
NONE,
kNonStrictMode),
int inlined_frame_index) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<SharedFunctionInfo> shared(function->shared());
- Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
- ScopeInfo<> scope_info(*serialized_scope_info);
+ Handle<ScopeInfo> scope_info(shared->scope_info());
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
// Allocate and initialize a JSObject with all the arguments, stack locals
isolate->factory()->NewJSObject(isolate->object_function());
// First fill all parameters.
- for (int i = 0; i < scope_info.number_of_parameters(); ++i) {
+ for (int i = 0; i < scope_info->ParameterCount(); ++i) {
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
SetProperty(local_scope,
- scope_info.parameter_name(i),
+ Handle<String>(scope_info->ParameterName(i)),
Handle<Object>(frame_inspector.GetParameter(i)),
NONE,
kNonStrictMode),
}
// Second fill all stack locals.
- for (int i = 0; i < scope_info.number_of_stack_slots(); ++i) {
+ for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
SetProperty(local_scope,
- scope_info.stack_slot_name(i),
+ Handle<String>(scope_info->StackLocalName(i)),
Handle<Object>(frame_inspector.GetExpression(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
}
- if (scope_info.number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
+ if (scope_info->HasContext()) {
// Third fill all context locals.
Handle<Context> frame_context(Context::cast(frame->context()));
Handle<Context> function_context(frame_context->declaration_context());
- if (!CopyContextLocalsToScopeObject(isolate,
- serialized_scope_info, scope_info,
- function_context, local_scope)) {
+ if (!CopyContextLocalsToScopeObject(
+ isolate, scope_info, function_context, local_scope)) {
return Handle<JSObject>();
}
ASSERT(context->IsFunctionContext());
Handle<SharedFunctionInfo> shared(context->closure()->shared());
- Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
- ScopeInfo<> scope_info(*serialized_scope_info);
+ Handle<ScopeInfo> scope_info(shared->scope_info());
// Allocate and initialize a JSObject with all the content of theis function
// closure.
isolate->factory()->NewJSObject(isolate->object_function());
// Fill all context locals to the context extension.
- if (!CopyContextLocalsToScopeObject(isolate,
- serialized_scope_info, scope_info,
- context, closure_scope)) {
+ if (!CopyContextLocalsToScopeObject(
+ isolate, scope_info, context, closure_scope)) {
return Handle<JSObject>();
}
Isolate* isolate,
Handle<Context> context) {
ASSERT(context->IsBlockContext());
- Handle<SerializedScopeInfo> serialized_scope_info(
- SerializedScopeInfo::cast(context->extension()));
- ScopeInfo<> scope_info(*serialized_scope_info);
+ Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
// Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function.
isolate->factory()->NewJSObject(isolate->object_function());
// Fill all context locals.
- if (scope_info.number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
- if (!CopyContextLocalsToScopeObject(isolate,
- serialized_scope_info, scope_info,
- context, block_scope)) {
- return Handle<JSObject>();
- }
+ if (!CopyContextLocalsToScopeObject(
+ isolate, scope_info, context, block_scope)) {
+ return Handle<JSObject>();
}
return block_scope;
// Return the type of the current scope.
ScopeType Type() {
if (!nested_scope_chain_.is_empty()) {
- Handle<SerializedScopeInfo> scope_info = nested_scope_chain_.last();
+ Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
switch (scope_info->Type()) {
case FUNCTION_SCOPE:
ASSERT(context_->IsFunctionContext() ||
return Handle<JSObject>();
}
- Handle<SerializedScopeInfo> CurrentScopeInfo() {
+ Handle<ScopeInfo> CurrentScopeInfo() {
if (!nested_scope_chain_.is_empty()) {
return nested_scope_chain_.last();
} else if (context_->IsBlockContext()) {
- return Handle<SerializedScopeInfo>(
- SerializedScopeInfo::cast(context_->extension()));
+ return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
} else if (context_->IsFunctionContext()) {
- return Handle<SerializedScopeInfo>(
- context_->closure()->shared()->scope_info());
+ return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
}
- return Handle<SerializedScopeInfo>::null();
+ return Handle<ScopeInfo>::null();
}
// Return the context for this scope. For the local context there might not
case ScopeIterator::ScopeTypeLocal: {
PrintF("Local:\n");
- ScopeInfo<> scope_info(function_->shared()->scope_info());
- scope_info.Print();
+ function_->shared()->scope_info()->Print();
if (!CurrentContext().is_null()) {
CurrentContext()->Print();
if (CurrentContext()->has_extension()) {
int inlined_frame_index_;
Handle<JSFunction> function_;
Handle<Context> context_;
- List<Handle<SerializedScopeInfo> > nested_scope_chain_;
+ List<Handle<ScopeInfo> > nested_scope_chain_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
};
JavaScriptFrame* frame,
int inlined_frame_index) {
HandleScope scope(isolate);
- List<Handle<SerializedScopeInfo> > scope_chain;
+ List<Handle<ScopeInfo> > scope_chain;
List<Handle<Context> > context_chain;
ScopeIterator it(isolate, frame, inlined_frame_index);
// Iteratively copy and or materialize the nested contexts.
while (!scope_chain.is_empty()) {
- Handle<SerializedScopeInfo> scope_info = scope_chain.RemoveLast();
+ Handle<ScopeInfo> scope_info = scope_chain.RemoveLast();
Handle<Context> current = context_chain.RemoveLast();
ASSERT(!(scope_info->HasContext() & current.is_null()));
JavaScriptFrame* frame,
int inlined_frame_index,
Handle<JSFunction> function,
- Handle<SerializedScopeInfo> scope_info,
- const ScopeInfo<>* sinfo,
+ Handle<ScopeInfo> scope_info,
Handle<Context> function_context) {
// Try to find the value of 'arguments' to pass as parameter. If it is not
// found (that is the debugged function does not reference 'arguments' and
// does not support eval) then create an 'arguments' object.
int index;
- if (sinfo->number_of_stack_slots() > 0) {
+ if (scope_info->StackLocalCount() > 0) {
index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
if (index != -1) {
return Handle<Object>(frame->GetExpression(index), isolate);
}
}
- if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
- index = scope_info->ContextSlotIndex(isolate->heap()->arguments_symbol(),
- NULL);
+ if (scope_info->HasHeapAllocatedLocals()) {
+ VariableMode mode;
+ index = scope_info->ContextSlotIndex(
+ isolate->heap()->arguments_symbol(), &mode);
if (index != -1) {
return Handle<Object>(function_context->get(index), isolate);
}
JavaScriptFrameIterator it(isolate, id);
JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(JSFunction::cast(frame->function()));
- Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
- ScopeInfo<> sinfo(*scope_info);
+ Handle<ScopeInfo> scope_info(function->shared()->scope_info());
// Traverse the saved contexts chain to find the active context for the
// selected frame.
isolate->factory()->undefined_value());
go_between->set_context(function->context());
#ifdef DEBUG
- ScopeInfo<> go_between_sinfo(go_between->shared()->scope_info());
- ASSERT(go_between_sinfo.number_of_parameters() == 0);
- ASSERT(go_between_sinfo.number_of_context_slots() == 0);
+ Handle<ScopeInfo> go_between_scope_info(go_between->shared()->scope_info());
+ ASSERT(go_between_scope_info->ParameterCount() == 0);
+ ASSERT(go_between_scope_info->ContextLocalCount() == 0);
#endif
// Materialize the content of the local scope into a JSObject.
Handle<Context> frame_context(Context::cast(frame->context()));
Handle<Context> function_context;
// Get the function's context if it has one.
- if (scope_info->HasHeapAllocatedLocals()) {
+ if (scope_info->HasContext()) {
function_context = Handle<Context>(frame_context->declaration_context());
}
context = CopyNestedScopeContextChain(isolate,
if (has_pending_exception) return Failure::Exception();
Handle<Object> arguments = GetArgumentsObject(isolate,
- frame, inlined_frame_index,
- function, scope_info,
- &sinfo, function_context);
+ frame,
+ inlined_frame_index,
+ function,
+ scope_info,
+ function_context);
// Invoke the evaluation function and return the result.
Handle<Object> argv[] = { arguments, source };
}
-template<class Allocator>
-ScopeInfo<Allocator>::ScopeInfo(Scope* scope)
- : function_name_(FACTORY->empty_symbol()),
- calls_eval_(scope->calls_eval()),
- is_strict_mode_(scope->is_strict_mode()),
- type_(scope->type()),
- parameters_(scope->num_parameters()),
- stack_slots_(scope->num_stack_slots()),
- context_slots_(scope->num_heap_slots()),
- context_modes_(scope->num_heap_slots()) {
- // Add parameters.
- for (int i = 0; i < scope->num_parameters(); i++) {
- ASSERT(parameters_.length() == i);
- parameters_.Add(scope->parameter(i)->name());
- }
-
- // Add stack locals and collect heap locals.
- // We are assuming that the locals' slots are allocated in
- // increasing order, so we can simply add them to the
- // ScopeInfo lists. However, due to usage analysis, this is
- // not true for context-allocated locals: Some of them
- // may be parameters which are allocated before the
- // non-parameter locals. When the non-parameter locals are
- // sorted according to usage, the allocated slot indices may
- // not be in increasing order with the variable list anymore.
- // Thus, we first collect the context-allocated locals, and then
- // sort them by context slot index before adding them to the
- // ScopeInfo list.
- List<Variable*, Allocator> locals(32); // 32 is a wild guess
- ASSERT(locals.is_empty());
- scope->CollectUsedVariables(&locals);
- locals.Sort(&CompareLocal);
-
- List<Variable*, Allocator> heap_locals(locals.length());
- for (int i = 0; i < locals.length(); i++) {
- Variable* var = locals[i];
- if (var->is_used()) {
- switch (var->location()) {
- case Variable::UNALLOCATED:
- case Variable::PARAMETER:
- break;
-
- case Variable::LOCAL:
- ASSERT(stack_slots_.length() == var->index());
- stack_slots_.Add(var->name());
- break;
-
- case Variable::CONTEXT:
- heap_locals.Add(var);
- break;
-
- case Variable::LOOKUP:
- // We don't expect lookup variables in the locals list.
- UNREACHABLE();
- break;
- }
+Handle<ScopeInfo> ScopeInfo::Create(Scope* scope) {
+ ZoneList<Variable*> variables(32); // 32 is a wild guess
+ ASSERT(variables.is_empty());
+ scope->CollectUsedVariables(&variables);
+
+ ZoneList<Variable*> stack_locals(scope->num_stack_slots());
+ ZoneList<Variable*> context_locals(scope->num_heap_slots());
+
+ // Collect stack and context locals.
+ for (int i = 0; i < variables.length(); i++) {
+ Variable* var = variables[i];
+ ASSERT(var->is_used());
+ switch (var->location()) {
+ case Variable::UNALLOCATED:
+ case Variable::PARAMETER:
+ break;
+
+ case Variable::LOCAL:
+ stack_locals.Add(var);
+ break;
+
+ case Variable::CONTEXT:
+ context_locals.Add(var);
+ break;
+
+ case Variable::LOOKUP:
+ // We don't expect lookup variables in the locals list.
+ UNREACHABLE();
+ break;
}
}
- // Add heap locals.
- if (scope->num_heap_slots() > 0) {
- // Add user-defined slots.
- for (int i = 0; i < heap_locals.length(); i++) {
- ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
- context_slots_.length());
- ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
- context_modes_.length());
- context_slots_.Add(heap_locals[i]->name());
- context_modes_.Add(heap_locals[i]->mode());
+ // Determine use and location of the function variable if it is present.
+ FunctionVariableInfo function_name_info;
+ VariableMode function_variable_mode;
+ if (scope->is_function_scope() && scope->function() != NULL) {
+ Variable* var = scope->function()->var();
+ if (!var->is_used()) {
+ function_name_info = UNUSED;
+ } else if (var->IsContextSlot()) {
+ function_name_info = CONTEXT;
+ } else {
+ ASSERT(var->IsStackLocal());
+ function_name_info = STACK;
}
-
+ function_variable_mode = var->mode();
} else {
- ASSERT(heap_locals.length() == 0);
+ function_name_info = NONE;
+ function_variable_mode = VAR;
}
- // Add the function context slot, if present.
- // For now, this must happen at the very end because of the
- // ordering of the scope info slots and the respective slot indices.
- if (scope->is_function_scope()) {
- VariableProxy* proxy = scope->function();
- if (proxy != NULL &&
- proxy->var()->is_used() &&
- proxy->var()->IsContextSlot()) {
- function_name_ = proxy->name();
- // Note that we must not find the function name in the context slot
- // list - instead it must be handled separately in the
- // Contexts::Lookup() function. Thus record an empty symbol here so we
- // get the correct number of context slots.
- ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
- context_slots_.length());
- ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
- context_modes_.length());
- context_slots_.Add(FACTORY->empty_symbol());
- context_modes_.Add(proxy->var()->mode());
- }
+ const bool has_function_name = function_name_info != NONE;
+ const int parameter_count = scope->num_parameters();
+ const int stack_local_count = stack_locals.length();
+ const int context_local_count = context_locals.length();
+ const int length = kVariablePartIndex
+ + parameter_count + stack_local_count + 2 * context_local_count
+ + (has_function_name ? 2 : 0);
+
+ Handle<ScopeInfo> scope_info = FACTORY->NewScopeInfo(length);
+
+ // Encode the flags.
+ int flags = TypeField::encode(scope->type()) |
+ CallsEvalField::encode(scope->calls_eval()) |
+ StrictModeField::encode(scope->is_strict_mode()) |
+ FunctionVariableField::encode(function_name_info) |
+ FunctionVariableMode::encode(function_variable_mode);
+ scope_info->SetFlags(flags);
+ scope_info->SetParameterCount(parameter_count);
+ scope_info->SetStackLocalCount(stack_local_count);
+ scope_info->SetContextLocalCount(context_local_count);
+
+ int index = kVariablePartIndex;
+ // Add parameters.
+ ASSERT(index == scope_info->ParameterEntriesIndex());
+ for (int i = 0; i < parameter_count; ++i) {
+ scope_info->set(index++, *scope->parameter(i)->name());
}
-}
+ // Add stack locals' names. We are assuming that the stack locals'
+ // slots are allocated in increasing order, so we can simply add
+ // them to the ScopeInfo object.
+ ASSERT(index == scope_info->StackLocalEntriesIndex());
+ for (int i = 0; i < stack_local_count; ++i) {
+ ASSERT(stack_locals[i]->index() == i);
+ scope_info->set(index++, *stack_locals[i]->name());
+ }
-// Encoding format in a FixedArray object:
-//
-// - function name
-//
-// - calls eval boolean flag
-//
-// - is strict mode scope
-//
-// - scope type
-//
-// - number of variables in the context object (smi) (= function context
-// slot index + 1)
-// - list of pairs (name, Var mode) of context-allocated variables (starting
-// with context slot 0)
-//
-// - number of parameters (smi)
-// - list of parameter names (starting with parameter 0 first)
-//
-// - number of variables on the stack (smi)
-// - list of names of stack-allocated variables (starting with stack slot 0)
+ // Due to usage analysis, context-allocated locals are not necessarily in
+ // increasing order: Some of them may be parameters which are allocated before
+ // the non-parameter locals. When the non-parameter locals are sorted
+ // according to usage, the allocated slot indices may not be in increasing
+ // order with the variable list anymore. Thus, we first need to sort them by
+ // context slot index before adding them to the ScopeInfo object.
+ context_locals.Sort(&CompareLocal);
+
+ // Add context locals' names.
+ ASSERT(index == scope_info->ContextLocalNameEntriesIndex());
+ for (int i = 0; i < context_local_count; ++i) {
+ scope_info->set(index++, *context_locals[i]->name());
+ }
-// The ScopeInfo representation could be simplified and the ScopeInfo
-// re-implemented (with almost the same interface). Here is a
-// suggestion for the new format:
-//
-// - have a single list with all variable names (parameters, stack locals,
-// context locals), followed by a list of non-Object* values containing
-// the variables information (what kind, index, attributes)
-// - searching the linear list of names is fast and yields an index into the
-// list if the variable name is found
-// - that list index is then used to find the variable information in the
-// subsequent list
-// - the list entries don't have to be in any particular order, so all the
-// current sorting business can go away
-// - the ScopeInfo lookup routines can be reduced to perhaps a single lookup
-// which returns all information at once
-// - when gathering the information from a Scope, we only need to iterate
-// through the local variables (parameters and context info is already
-// present)
+ // Add context locals' modes.
+ ASSERT(index == scope_info->ContextLocalModeEntriesIndex());
+ for (int i = 0; i < context_local_count; ++i) {
+ scope_info->set(index++, Smi::FromInt(context_locals[i]->mode()));
+ }
+ // If present, add the function variable name and its index.
+ ASSERT(index == scope_info->FunctionNameEntryIndex());
+ if (has_function_name) {
+ int var_index = scope->function()->var()->index();
+ scope_info->set(index++, *scope->function()->name());
+ scope_info->set(index++, Smi::FromInt(var_index));
+ ASSERT(function_name_info != STACK ||
+ (var_index == scope_info->StackLocalCount() &&
+ var_index == scope_info->StackSlotCount() - 1));
+ ASSERT(function_name_info != CONTEXT ||
+ var_index == scope_info->ContextLength() - 1);
+ }
-template <class T>
-static inline Object** ReadInt(Object** p, T* x) {
- *x = static_cast<T>((reinterpret_cast<Smi*>(*p++))->value());
- return p;
+ ASSERT(index == scope_info->length());
+ ASSERT(scope->num_parameters() == scope_info->ParameterCount());
+ ASSERT(scope->num_stack_slots() == scope_info->StackSlotCount());
+ ASSERT(scope->num_heap_slots() == scope_info->ContextLength());
+ return scope_info;
}
-static inline Object** ReadBool(Object** p, bool* x) {
- *x = (reinterpret_cast<Smi*>(*p++))->value() != 0;
- return p;
+ScopeInfo* ScopeInfo::Empty() {
+ return reinterpret_cast<ScopeInfo*>(HEAP->empty_fixed_array());
}
-template <class T>
-static inline Object** ReadObject(Object** p, Handle<T>* s) {
- *s = Handle<T>::cast(Handle<Object>(*p++));
- return p;
+ScopeType ScopeInfo::Type() {
+ ASSERT(length() > 0);
+ return TypeField::decode(Flags());
}
-template <class Allocator, class T>
-static Object** ReadList(Object** p, List<Handle<T>, Allocator >* list) {
- ASSERT(list->is_empty());
- int n;
- p = ReadInt(p, &n);
- while (n-- > 0) {
- Handle<T> s;
- p = ReadObject(p, &s);
- list->Add(s);
- }
- return p;
-}
-
-
-template <class Allocator>
-static Object** ReadList(Object** p,
- List<Handle<String>, Allocator>* list,
- List<VariableMode, Allocator>* modes) {
- ASSERT(list->is_empty());
- int n;
- p = ReadInt(p, &n);
- while (n-- > 0) {
- Handle<String> s;
- int m;
- p = ReadObject(p, &s);
- p = ReadInt(p, &m);
- list->Add(s);
- modes->Add(static_cast<VariableMode>(m));
- }
- return p;
-}
-
-
-template<class Allocator>
-ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
- : function_name_(FACTORY->empty_symbol()),
- parameters_(4),
- stack_slots_(8),
- context_slots_(8),
- context_modes_(8) {
- if (data->length() > 0) {
- Object** p0 = data->data_start();
- Object** p = p0;
- p = ReadObject(p, &function_name_);
- p = ReadBool(p, &calls_eval_);
- p = ReadBool(p, &is_strict_mode_);
- p = ReadInt(p, &type_);
- p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
- p = ReadList<Allocator>(p, ¶meters_);
- p = ReadList<Allocator>(p, &stack_slots_);
- ASSERT((p - p0) == FixedArray::cast(data)->length());
- }
+bool ScopeInfo::CallsEval() {
+ return length() > 0 && CallsEvalField::decode(Flags());
}
-static inline Object** WriteInt(Object** p, int x) {
- *p++ = Smi::FromInt(x);
- return p;
+bool ScopeInfo::IsStrictMode() {
+ return length() > 0 && StrictModeField::decode(Flags());
}
-static inline Object** WriteBool(Object** p, bool b) {
- *p++ = Smi::FromInt(b ? 1 : 0);
- return p;
+int ScopeInfo::LocalCount() {
+ return StackLocalCount() + ContextLocalCount();
}
-template <class T>
-static inline Object** WriteObject(Object** p, Handle<T> s) {
- *p++ = *s;
- return p;
+int ScopeInfo::StackSlotCount() {
+ if (length() > 0) {
+ bool function_name_stack_slot =
+ FunctionVariableField::decode(Flags()) == STACK;
+ return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
+ }
+ return 0;
}
-template <class Allocator, class T>
-static Object** WriteList(Object** p, List<Handle<T>, Allocator >* list) {
- const int n = list->length();
- p = WriteInt(p, n);
- for (int i = 0; i < n; i++) {
- p = WriteObject(p, list->at(i));
+int ScopeInfo::ContextLength() {
+ if (length() > 0) {
+ int context_locals = ContextLocalCount();
+ bool function_name_context_slot =
+ FunctionVariableField::decode(Flags()) == CONTEXT;
+ bool has_context = context_locals > 0 ||
+ function_name_context_slot ||
+ Type() == WITH_SCOPE ||
+ (Type() == FUNCTION_SCOPE && CallsEval());
+ if (has_context) {
+ return Context::MIN_CONTEXT_SLOTS + context_locals +
+ (function_name_context_slot ? 1 : 0);
+ }
}
- return p;
+ return 0;
}
-template <class Allocator>
-static Object** WriteList(Object** p,
- List<Handle<String>, Allocator>* list,
- List<VariableMode, Allocator>* modes) {
- const int n = list->length();
- p = WriteInt(p, n);
- for (int i = 0; i < n; i++) {
- p = WriteObject(p, list->at(i));
- p = WriteInt(p, modes->at(i));
- }
- return p;
-}
-
-
-template<class Allocator>
-Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
- // function name, calls eval, is_strict_mode, scope type,
- // length for 3 tables:
- const int extra_slots = 1 + 1 + 1 + 1 + 3;
- int length = extra_slots +
- context_slots_.length() * 2 +
- parameters_.length() +
- stack_slots_.length();
-
- Handle<SerializedScopeInfo> data(
- SerializedScopeInfo::cast(*FACTORY->NewSerializedScopeInfo(length)));
- AssertNoAllocation nogc;
-
- Object** p0 = data->data_start();
- Object** p = p0;
- p = WriteObject(p, function_name_);
- p = WriteBool(p, calls_eval_);
- p = WriteBool(p, is_strict_mode_);
- p = WriteInt(p, type_);
- p = WriteList(p, &context_slots_, &context_modes_);
- p = WriteList(p, ¶meters_);
- p = WriteList(p, &stack_slots_);
- ASSERT((p - p0) == length);
-
- return data;
-}
-
-
-template<class Allocator>
-Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
- // A local variable can be allocated either on the stack or in the context.
- // For variables allocated in the context they are always preceded by
- // Context::MIN_CONTEXT_SLOTS of fixed allocated slots in the context.
- if (i < number_of_stack_slots()) {
- return stack_slot_name(i);
+bool ScopeInfo::HasFunctionName() {
+ if (length() > 0) {
+ return NONE != FunctionVariableField::decode(Flags());
} else {
- return context_slot_name(i - number_of_stack_slots() +
- Context::MIN_CONTEXT_SLOTS);
+ return false;
}
}
-template<class Allocator>
-int ScopeInfo<Allocator>::NumberOfLocals() const {
- int number_of_locals = number_of_stack_slots();
- if (number_of_context_slots() > 0) {
- ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
- number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
+bool ScopeInfo::HasHeapAllocatedLocals() {
+ if (length() > 0) {
+ return ContextLocalCount() > 0;
+ } else {
+ return false;
}
- return number_of_locals;
-}
-
-
-Handle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) {
- ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
- return sinfo.Serialize();
-}
-
-
-SerializedScopeInfo* SerializedScopeInfo::Empty() {
- return reinterpret_cast<SerializedScopeInfo*>(HEAP->empty_fixed_array());
-}
-
-
-Object** SerializedScopeInfo::ContextEntriesAddr() {
- ASSERT(length() > 0);
- // +4 for function name, calls eval, strict mode, scope type.
- return data_start() + 4;
-}
-
-
-Object** SerializedScopeInfo::ParameterEntriesAddr() {
- ASSERT(length() > 0);
- Object** p = ContextEntriesAddr();
- int number_of_context_slots;
- p = ReadInt(p, &number_of_context_slots);
- return p + number_of_context_slots*2; // *2 for pairs
-}
-
-
-Object** SerializedScopeInfo::StackSlotEntriesAddr() {
- ASSERT(length() > 0);
- Object** p = ParameterEntriesAddr();
- int number_of_parameter_slots;
- p = ReadInt(p, &number_of_parameter_slots);
- return p + number_of_parameter_slots;
}
-bool SerializedScopeInfo::CallsEval() {
+bool ScopeInfo::HasContext() {
if (length() > 0) {
- Object** p = data_start() + 1; // +1 for function name.
- bool calls_eval;
- p = ReadBool(p, &calls_eval);
- return calls_eval;
+ return ContextLength() > 0;
+ } else {
+ return false;
}
- return false;
}
-bool SerializedScopeInfo::IsStrictMode() {
- if (length() > 0) {
- Object** p = data_start() + 2; // +2 for function name, calls eval.
- bool strict_mode;
- p = ReadBool(p, &strict_mode);
- return strict_mode;
- }
- return false;
+String* ScopeInfo::FunctionName() {
+ ASSERT(HasFunctionName());
+ return String::cast(get(FunctionNameEntryIndex()));
}
-ScopeType SerializedScopeInfo::Type() {
- ASSERT(length() > 0);
- // +3 for function name, calls eval, strict mode.
- Object** p = data_start() + 3;
- ScopeType type;
- p = ReadInt(p, &type);
- return type;
+String* ScopeInfo::ParameterName(int var) {
+ ASSERT(0 <= var && var < ParameterCount());
+ int info_index = ParameterEntriesIndex() + var;
+ return String::cast(get(info_index));
}
-int SerializedScopeInfo::NumberOfStackSlots() {
- if (length() > 0) {
- Object** p = StackSlotEntriesAddr();
- int number_of_stack_slots;
- ReadInt(p, &number_of_stack_slots);
- return number_of_stack_slots;
- }
- return 0;
+String* ScopeInfo::LocalName(int var) {
+ ASSERT(0 <= var && var < LocalCount());
+ ASSERT(StackLocalEntriesIndex() + StackLocalCount() ==
+ ContextLocalNameEntriesIndex());
+ int info_index = StackLocalEntriesIndex() + var;
+ return String::cast(get(info_index));
}
-int SerializedScopeInfo::NumberOfContextSlots() {
- if (length() > 0) {
- Object** p = ContextEntriesAddr();
- int number_of_context_slots;
- ReadInt(p, &number_of_context_slots);
- return number_of_context_slots + Context::MIN_CONTEXT_SLOTS;
- }
- return 0;
+String* ScopeInfo::StackLocalName(int var) {
+ ASSERT(0 <= var && var < StackLocalCount());
+ int info_index = StackLocalEntriesIndex() + var;
+ return String::cast(get(info_index));
}
-bool SerializedScopeInfo::HasHeapAllocatedLocals() {
- if (length() > 0) {
- Object** p = ContextEntriesAddr();
- int number_of_context_slots;
- ReadInt(p, &number_of_context_slots);
- return number_of_context_slots > 0;
- }
- return false;
+String* ScopeInfo::ContextLocalName(int var) {
+ ASSERT(0 <= var && var < ContextLocalCount());
+ int info_index = ContextLocalNameEntriesIndex() + var;
+ return String::cast(get(info_index));
}
-bool SerializedScopeInfo::HasContext() {
- return HasHeapAllocatedLocals() ||
- Type() == WITH_SCOPE;
+VariableMode ScopeInfo::ContextLocalMode(int var) {
+ ASSERT(0 <= var && var < ContextLocalCount());
+ int info_index = ContextLocalModeEntriesIndex() + var;
+ return static_cast<VariableMode>(Smi::cast(get(info_index))->value());
}
-int SerializedScopeInfo::StackSlotIndex(String* name) {
+int ScopeInfo::StackSlotIndex(String* name) {
ASSERT(name->IsSymbol());
if (length() > 0) {
- // Slots start after length entry.
- Object** p0 = StackSlotEntriesAddr();
- int number_of_stack_slots;
- p0 = ReadInt(p0, &number_of_stack_slots);
- Object** p = p0;
- Object** end = p0 + number_of_stack_slots;
- while (p != end) {
- if (*p == name) return static_cast<int>(p - p0);
- p++;
+ int start = StackLocalEntriesIndex();
+ int end = StackLocalEntriesIndex() + StackLocalCount();
+ for (int i = start; i < end; ++i) {
+ if (name == get(i)) {
+ return i - start;
+ }
}
}
return -1;
}
-int SerializedScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
+
+int ScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
ASSERT(name->IsSymbol());
- Isolate* isolate = GetIsolate();
- int result = isolate->context_slot_cache()->Lookup(this, name, mode);
- if (result != ContextSlotCache::kNotFound) return result;
+ ASSERT(mode != NULL);
if (length() > 0) {
- // Slots start after length entry.
- Object** p0 = ContextEntriesAddr();
- int number_of_context_slots;
- p0 = ReadInt(p0, &number_of_context_slots);
- Object** p = p0;
- Object** end = p0 + number_of_context_slots * 2;
- while (p != end) {
- if (*p == name) {
- ASSERT(((p - p0) & 1) == 0);
- int v;
- ReadInt(p + 1, &v);
- VariableMode mode_value = static_cast<VariableMode>(v);
- if (mode != NULL) *mode = mode_value;
- result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
- isolate->context_slot_cache()->Update(this, name, mode_value, result);
+ ContextSlotCache* context_slot_cache = GetIsolate()->context_slot_cache();
+ int result = context_slot_cache->Lookup(this, name, mode);
+ if (result != ContextSlotCache::kNotFound) {
+ ASSERT(result < ContextLength());
+ return result;
+ }
+
+ int start = ContextLocalNameEntriesIndex();
+ int end = ContextLocalNameEntriesIndex() + ContextLocalCount();
+ for (int i = start; i < end; ++i) {
+ if (name == get(i)) {
+ int var = i - start;
+ *mode = ContextLocalMode(var);
+ result = Context::MIN_CONTEXT_SLOTS + var;
+ context_slot_cache->Update(this, name, *mode, result);
+ ASSERT(result < ContextLength());
return result;
}
- p += 2;
}
+ context_slot_cache->Update(this, name, INTERNAL, -1);
}
- isolate->context_slot_cache()->Update(this, name, INTERNAL, -1);
return -1;
}
-int SerializedScopeInfo::ParameterIndex(String* name) {
+int ScopeInfo::ParameterIndex(String* name) {
ASSERT(name->IsSymbol());
if (length() > 0) {
// We must read parameters from the end since for
// last declaration of that parameter is used
// inside a function (and thus we need to look
// at the last index). Was bug# 1110337.
- //
- // Eventually, we should only register such parameters
- // once, with corresponding index. This requires a new
- // implementation of the ScopeInfo code. See also other
- // comments in this file regarding this.
- Object** p = ParameterEntriesAddr();
- int number_of_parameter_slots;
- Object** p0 = ReadInt(p, &number_of_parameter_slots);
- p = p0 + number_of_parameter_slots;
- while (p > p0) {
- p--;
- if (*p == name) return static_cast<int>(p - p0);
+ int start = ParameterEntriesIndex();
+ int end = ParameterEntriesIndex() + ParameterCount();
+ for (int i = end - 1; i >= start; --i) {
+ if (name == get(i)) {
+ return i - start;
+ }
}
}
return -1;
}
-int SerializedScopeInfo::FunctionContextSlotIndex(String* name,
- VariableMode* mode) {
+int ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
ASSERT(name->IsSymbol());
+ ASSERT(mode != NULL);
if (length() > 0) {
- Object** p = data_start();
- if (*p == name) {
- p = ContextEntriesAddr();
- int number_of_context_slots;
- p = ReadInt(p, &number_of_context_slots);
- ASSERT(number_of_context_slots != 0);
- // The function context slot is the last entry.
- if (mode != NULL) {
- // Seek to context slot entry.
- p += (number_of_context_slots - 1) * 2;
- // Seek to mode.
- ++p;
- ReadInt(p, mode);
- }
- return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
+ if (FunctionVariableField::decode(Flags()) == CONTEXT &&
+ FunctionName() == name) {
+ *mode = FunctionVariableMode::decode(Flags());
+ return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
}
}
return -1;
}
+int ScopeInfo::ParameterEntriesIndex() {
+ ASSERT(length() > 0);
+ return kVariablePartIndex;
+}
+
+
+int ScopeInfo::StackLocalEntriesIndex() {
+ return ParameterEntriesIndex() + ParameterCount();
+}
+
+
+int ScopeInfo::ContextLocalNameEntriesIndex() {
+ return StackLocalEntriesIndex() + StackLocalCount();
+}
+
+
+int ScopeInfo::ContextLocalModeEntriesIndex() {
+ return ContextLocalNameEntriesIndex() + ContextLocalCount();
+}
+
+
+int ScopeInfo::FunctionNameEntryIndex() {
+ return ContextLocalModeEntriesIndex() + ContextLocalCount();
+}
+
+
int ContextSlotCache::Hash(Object* data, String* name) {
// Uses only lower 32 bits if pointers are larger.
uintptr_t addr_hash =
}
-template <class Allocator>
static void PrintList(const char* list_name,
int nof_internal_slots,
- List<Handle<String>, Allocator>& list) {
- if (list.length() > 0) {
+ int start,
+ int end,
+ ScopeInfo* scope_info) {
+ if (start < end) {
PrintF("\n // %s\n", list_name);
if (nof_internal_slots > 0) {
PrintF(" %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
}
- for (int i = 0; i < list.length(); i++) {
- PrintF(" %2d ", i + nof_internal_slots);
- list[i]->ShortPrint();
+ for (int i = nof_internal_slots; start < end; ++i, ++start) {
+ PrintF(" %2d ", i);
+ String::cast(scope_info->get(start))->ShortPrint();
PrintF("\n");
}
}
}
-template<class Allocator>
-void ScopeInfo<Allocator>::Print() {
+void ScopeInfo::Print() {
PrintF("ScopeInfo ");
- if (function_name_->length() > 0)
- function_name_->ShortPrint();
- else
+ if (HasFunctionName()) {
+ FunctionName()->ShortPrint();
+ } else {
PrintF("/* no function name */");
+ }
PrintF("{");
- PrintList<Allocator>("parameters", 0, parameters_);
- PrintList<Allocator>("stack slots", 0, stack_slots_);
- PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS,
- context_slots_);
+ PrintList("parameters", 0,
+ ParameterEntriesIndex(),
+ ParameterEntriesIndex() + ParameterCount(),
+ this);
+ PrintList("stack slots", 0,
+ StackLocalEntriesIndex(),
+ StackLocalEntriesIndex() + StackLocalCount(),
+ this);
+ PrintList("context slots",
+ Context::MIN_CONTEXT_SLOTS,
+ ContextLocalNameEntriesIndex(),
+ ContextLocalNameEntriesIndex() + ContextLocalCount(),
+ this);
PrintF("}\n");
}
#endif // DEBUG
-
-// Make sure the classes get instantiated by the template system.
-template class ScopeInfo<FreeStoreAllocationPolicy>;
-template class ScopeInfo<PreallocatedStorage>;
-template class ScopeInfo<ZoneListAllocationPolicy>;
-
} } // namespace v8::internal
namespace v8 {
namespace internal {
-// ScopeInfo represents information about different scopes of a source
-// program and the allocation of the scope's variables. Scope information
-// is stored in a compressed form in SerializedScopeInfo objects and is used
-// at runtime (stack dumps, deoptimization, etc.).
-
-// Forward defined as
-// template <class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
-template<class Allocator>
-class ScopeInfo BASE_EMBEDDED {
- public:
- // Create a ScopeInfo instance from a scope.
- explicit ScopeInfo(Scope* scope);
-
- // Create a ScopeInfo instance from SerializedScopeInfo.
- explicit ScopeInfo(SerializedScopeInfo* data);
-
- // Creates a SerializedScopeInfo holding the serialized scope info.
- Handle<SerializedScopeInfo> Serialize();
-
- // --------------------------------------------------------------------------
- // Lookup
-
- Handle<String> function_name() const { return function_name_; }
-
- Handle<String> parameter_name(int i) const { return parameters_[i]; }
- int number_of_parameters() const { return parameters_.length(); }
-
- Handle<String> stack_slot_name(int i) const { return stack_slots_[i]; }
- int number_of_stack_slots() const { return stack_slots_.length(); }
-
- Handle<String> context_slot_name(int i) const {
- return context_slots_[i - Context::MIN_CONTEXT_SLOTS];
- }
- int number_of_context_slots() const {
- int l = context_slots_.length();
- return l == 0 ? 0 : l + Context::MIN_CONTEXT_SLOTS;
- }
-
- Handle<String> LocalName(int i) const;
- int NumberOfLocals() const;
-
- ScopeType type() const { return type_; }
- // --------------------------------------------------------------------------
- // Debugging support
-
-#ifdef DEBUG
- void Print();
-#endif
-
- private:
- Handle<String> function_name_;
- bool calls_eval_;
- bool is_strict_mode_;
- ScopeType type_;
- List<Handle<String>, Allocator > parameters_;
- List<Handle<String>, Allocator > stack_slots_;
- List<Handle<String>, Allocator > context_slots_;
- List<VariableMode, Allocator > context_modes_;
-};
-
-
// Cache for mapping (data, property name) into context slot index.
// The cache contains both positive and negative results.
// Slot index equals -1 means the property is absent.
unresolved_(16),
decls_(4),
already_resolved_(false) {
- SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
+ SetDefaults(type, outer_scope, Handle<ScopeInfo>::null());
// At some point we might want to provide outer scopes to
// eval scopes (by walking the stack and reading the scope info).
// In that case, the ASSERT below needs to be adjusted.
Scope::Scope(Scope* inner_scope,
ScopeType type,
- Handle<SerializedScopeInfo> scope_info)
+ Handle<ScopeInfo> scope_info)
: isolate_(Isolate::Current()),
inner_scopes_(4),
variables_(),
decls_(4),
already_resolved_(true) {
SetDefaults(type, NULL, scope_info);
- if (!scope_info.is_null() && scope_info->HasHeapAllocatedLocals()) {
- num_heap_slots_ = scope_info_->NumberOfContextSlots();
+ if (!scope_info.is_null()) {
+ num_heap_slots_ = scope_info_->ContextLength();
}
AddInnerScope(inner_scope);
}
unresolved_(0),
decls_(0),
already_resolved_(true) {
- SetDefaults(CATCH_SCOPE, NULL, Handle<SerializedScopeInfo>::null());
+ SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null());
AddInnerScope(inner_scope);
++num_var_or_const_;
Variable* variable = variables_.Declare(this,
void Scope::SetDefaults(ScopeType type,
Scope* outer_scope,
- Handle<SerializedScopeInfo> scope_info) {
+ Handle<ScopeInfo> scope_info) {
outer_scope_ = outer_scope;
type_ = type;
scope_name_ = isolate_->factory()->empty_symbol();
bool contains_with = false;
while (!context->IsGlobalContext()) {
if (context->IsWithContext()) {
- Scope* with_scope = new Scope(current_scope, WITH_SCOPE,
- Handle<SerializedScopeInfo>::null());
+ Scope* with_scope = new Scope(current_scope,
+ WITH_SCOPE,
+ Handle<ScopeInfo>::null());
current_scope = with_scope;
// All the inner scopes are inside a with.
contains_with = true;
s->scope_inside_with_ = true;
}
} else if (context->IsFunctionContext()) {
- SerializedScopeInfo* scope_info =
- context->closure()->shared()->scope_info();
- current_scope = new Scope(current_scope, FUNCTION_SCOPE,
- Handle<SerializedScopeInfo>(scope_info));
+ ScopeInfo* scope_info = context->closure()->shared()->scope_info();
+ current_scope = new Scope(current_scope,
+ FUNCTION_SCOPE,
+ Handle<ScopeInfo>(scope_info));
} else if (context->IsBlockContext()) {
- SerializedScopeInfo* scope_info =
- SerializedScopeInfo::cast(context->extension());
- current_scope = new Scope(current_scope, BLOCK_SCOPE,
- Handle<SerializedScopeInfo>(scope_info));
+ ScopeInfo* scope_info = ScopeInfo::cast(context->extension());
+ current_scope = new Scope(current_scope,
+ BLOCK_SCOPE,
+ Handle<ScopeInfo>(scope_info));
} else {
ASSERT(context->IsCatchContext());
String* name = String::cast(context->extension());
index = scope_info_->ParameterIndex(*name);
if (index < 0) {
// Check the function name.
- index = scope_info_->FunctionContextSlotIndex(*name, NULL);
+ index = scope_info_->FunctionContextSlotIndex(*name, &mode);
if (index < 0) return NULL;
}
}
}
-template<class Allocator>
-void Scope::CollectUsedVariables(List<Variable*, Allocator>* locals) {
+void Scope::CollectUsedVariables(ZoneList<Variable*>* locals) {
// Collect variables in this scope.
// Note that the function_ variable - if present - is not
// collected here but handled separately in ScopeInfo
}
-// Make sure the method gets instantiated by the template system.
-template void Scope::CollectUsedVariables(
- List<Variable*, FreeStoreAllocationPolicy>* locals);
-template void Scope::CollectUsedVariables(
- List<Variable*, PreallocatedStorage>* locals);
-template void Scope::CollectUsedVariables(
- List<Variable*, ZoneListAllocationPolicy>* locals);
-
-
void Scope::AllocateVariables(Handle<Context> context) {
ASSERT(outer_scope_ == NULL); // eval or global scopes only
}
-Handle<SerializedScopeInfo> Scope::GetSerializedScopeInfo() {
+Handle<ScopeInfo> Scope::GetScopeInfo() {
if (scope_info_.is_null()) {
- scope_info_ = SerializedScopeInfo::Create(this);
+ scope_info_ = ScopeInfo::Create(this);
}
return scope_info_;
}
void Scope::GetNestedScopeChain(
- List<Handle<SerializedScopeInfo> >* chain,
+ List<Handle<ScopeInfo> >* chain,
int position) {
- chain->Add(Handle<SerializedScopeInfo>(GetSerializedScopeInfo()));
+ chain->Add(Handle<ScopeInfo>(GetScopeInfo()));
for (int i = 0; i < inner_scopes_.length(); i++) {
Scope* scope = inner_scopes_[i];
if (is_function_scope()) AllocateParameterLocals();
AllocateNonParameterLocals();
- // Allocate context if necessary.
- bool must_have_local_context = false;
- if (scope_calls_eval_ || scope_contains_with_) {
- // The context for the eval() call or 'with' statement in this scope.
- // Unless we are in the global or an eval scope, we need a local
- // context even if we didn't statically allocate any locals in it,
- // and the compiler will access the context variable. If we are
- // not in an inner scope, the scope is provided from the outside.
- must_have_local_context = is_function_scope();
- }
+ // Force allocation of a context for this scope if necessary. For a 'with'
+ // scope and for a function scope that makes an 'eval' call we need a context,
+ // even if no local variables were statically allocated in the scope.
+ bool must_have_context = is_with_scope() ||
+ (is_function_scope() && calls_eval());
// If we didn't allocate any locals in the local context, then we only
- // need the minimal number of slots if we must have a local context.
- if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
- !must_have_local_context) {
+ // need the minimal number of slots if we must have a context.
+ if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && !must_have_context) {
num_heap_slots_ = 0;
}
// Variable allocation.
// Collect all used locals in this scope.
- template<class Allocator>
- void CollectUsedVariables(List<Variable*, Allocator>* locals);
+ void CollectUsedVariables(ZoneList<Variable*>* locals);
// Resolve and fill in the allocation information for all variables
// in this scopes. Must be called *after* all scopes have been
// where var declarations will be hoisted to in the implementation.
Scope* DeclarationScope();
- Handle<SerializedScopeInfo> GetSerializedScopeInfo();
+ Handle<ScopeInfo> GetScopeInfo();
// Get the chain of nested scopes within this scope for the source statement
// position. The scopes will be added to the list from the outermost scope to
// the innermost scope. Only nested block, catch or with scopes are tracked
// and will be returned, but no inner function scopes.
- void GetNestedScopeChain(List<Handle<SerializedScopeInfo> >* chain,
+ void GetNestedScopeChain(List<Handle<ScopeInfo> >* chain,
int statement_position);
// ---------------------------------------------------------------------------
int num_stack_slots_;
int num_heap_slots_;
- // Serialized scopes support.
- Handle<SerializedScopeInfo> scope_info_;
+ // Serialized scope info support.
+ Handle<ScopeInfo> scope_info_;
bool already_resolved() { return already_resolved_; }
// Create a non-local variable with a given name.
private:
// Construct a scope based on the scope info.
- Scope(Scope* inner_scope,
- ScopeType type,
- Handle<SerializedScopeInfo> scope_info);
+ Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info);
// Construct a catch scope with a binding for the name.
Scope(Scope* inner_scope, Handle<String> catch_variable_name);
void SetDefaults(ScopeType type,
Scope* outer_scope,
- Handle<SerializedScopeInfo> scope_info);
+ Handle<ScopeInfo> scope_info);
};
} } // namespace v8::internal
ASSERT(!o->IsScript());
return o->IsString() || o->IsSharedFunctionInfo() ||
o->IsHeapNumber() || o->IsCode() ||
- o->IsSerializedScopeInfo() ||
+ o->IsScopeInfo() ||
o->map() == HEAP->fixed_cow_array_map();
}
class RegExpCompiler;
class RegExpVisitor;
class Scope;
-template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
-class SerializedScopeInfo;
+class ScopeInfo;
class Script;
class Slot;
class Smi;