Create a separate class to encapsulate ScopeInfo serialization.
The static ScopeInfo members moved into this class. The new class is named ScopeInfoObject which I am not proud of, better ideas are very welcome. Also got rid of the sentinels in the serialized scope info which saves 3 words per function and is not slower. Review URL: http://codereview.chromium.org/2908009 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5067 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
3bc97b7d34
commit
db23321704
@ -549,8 +549,8 @@ Object* Accessors::FunctionGetArguments(Object* object, void*) {
|
|||||||
if (frame->function() != *function) continue;
|
if (frame->function() != *function) continue;
|
||||||
|
|
||||||
// If there is an arguments variable in the stack, we return that.
|
// If there is an arguments variable in the stack, we return that.
|
||||||
int index = ScopeInfo<>::StackSlotIndex(function->shared()->scope_info(),
|
int index = function->shared()->scope_info()->
|
||||||
Heap::arguments_symbol());
|
StackSlotIndex(Heap::arguments_symbol());
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
Handle<Object> arguments = Handle<Object>(frame->GetExpression(index));
|
Handle<Object> arguments = Handle<Object>(frame->GetExpression(index));
|
||||||
if (!arguments->IsTheHole()) return *arguments;
|
if (!arguments->IsTheHole()) return *arguments;
|
||||||
|
@ -160,7 +160,7 @@ Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
|
|||||||
Handle<Code> code = MakeCode(context, info);
|
Handle<Code> code = MakeCode(context, info);
|
||||||
if (!info->shared_info().is_null()) {
|
if (!info->shared_info().is_null()) {
|
||||||
info->shared_info()->set_scope_info(
|
info->shared_info()->set_scope_info(
|
||||||
*ScopeInfo<>::CreateHeapObject(info->scope()));
|
*SerializedScopeInfo::Create(info->scope()));
|
||||||
}
|
}
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
@ -262,7 +262,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
|
|||||||
lit->name(),
|
lit->name(),
|
||||||
lit->materialized_literal_count(),
|
lit->materialized_literal_count(),
|
||||||
code,
|
code,
|
||||||
ScopeInfo<>::CreateHeapObject(info.scope()));
|
SerializedScopeInfo::Create(info.scope()));
|
||||||
|
|
||||||
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
||||||
Compiler::SetFunctionInfo(result, lit, true, script);
|
Compiler::SetFunctionInfo(result, lit, true, script);
|
||||||
@ -450,7 +450,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
|
|||||||
|
|
||||||
// Update the shared function info with the compiled code and the scope info.
|
// Update the shared function info with the compiled code and the scope info.
|
||||||
shared->set_code(*code);
|
shared->set_code(*code);
|
||||||
shared->set_scope_info(*ScopeInfo<>::CreateHeapObject(info->scope()));
|
shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
|
||||||
|
|
||||||
// Set the expected number of properties for instances.
|
// Set the expected number of properties for instances.
|
||||||
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
|
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
|
||||||
@ -485,7 +485,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
|
|||||||
bool allow_lazy = literal->AllowsLazyCompilation() &&
|
bool allow_lazy = literal->AllowsLazyCompilation() &&
|
||||||
!LiveEditFunctionTracker::IsActive();
|
!LiveEditFunctionTracker::IsActive();
|
||||||
|
|
||||||
Handle<Object> scope_info(ScopeInfo<>::EmptyHeapObject());
|
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
|
||||||
|
|
||||||
// Generate code
|
// Generate code
|
||||||
Handle<Code> code;
|
Handle<Code> code;
|
||||||
@ -568,7 +568,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
|
|||||||
literal->start_position(),
|
literal->start_position(),
|
||||||
script,
|
script,
|
||||||
code);
|
code);
|
||||||
scope_info = ScopeInfo<>::CreateHeapObject(info.scope());
|
scope_info = SerializedScopeInfo::Create(info.scope());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a shared function info object.
|
// Create a shared function info object.
|
||||||
|
@ -120,9 +120,10 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
|
|||||||
// we have context-local slots
|
// we have context-local slots
|
||||||
|
|
||||||
// check non-parameter locals in context
|
// check non-parameter locals in context
|
||||||
Handle<Object> scope_info(context->closure()->shared()->scope_info());
|
Handle<SerializedScopeInfo> scope_info(
|
||||||
|
context->closure()->shared()->scope_info());
|
||||||
Variable::Mode mode;
|
Variable::Mode mode;
|
||||||
int index = ScopeInfo<>::ContextSlotIndex(*scope_info, *name, &mode);
|
int index = scope_info->ContextSlotIndex(*name, &mode);
|
||||||
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
|
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
// slot found
|
// slot found
|
||||||
@ -150,13 +151,11 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check parameter locals in context
|
// check parameter locals in context
|
||||||
int param_index = ScopeInfo<>::ParameterIndex(*scope_info, *name);
|
int param_index = scope_info->ParameterIndex(*name);
|
||||||
if (param_index >= 0) {
|
if (param_index >= 0) {
|
||||||
// slot found.
|
// slot found.
|
||||||
int index =
|
int index =
|
||||||
ScopeInfo<>::ContextSlotIndex(*scope_info,
|
scope_info->ContextSlotIndex(Heap::arguments_shadow_symbol(), NULL);
|
||||||
Heap::arguments_shadow_symbol(),
|
|
||||||
NULL);
|
|
||||||
ASSERT(index >= 0); // arguments must exist and be in the heap context
|
ASSERT(index >= 0); // arguments must exist and be in the heap context
|
||||||
Handle<JSObject> arguments(JSObject::cast(context->get(index)));
|
Handle<JSObject> arguments(JSObject::cast(context->get(index)));
|
||||||
ASSERT(arguments->HasLocalProperty(Heap::length_symbol()));
|
ASSERT(arguments->HasLocalProperty(Heap::length_symbol()));
|
||||||
@ -170,7 +169,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
|
|||||||
|
|
||||||
// check intermediate context (holding only the function name variable)
|
// check intermediate context (holding only the function name variable)
|
||||||
if (follow_context_chain) {
|
if (follow_context_chain) {
|
||||||
int index = ScopeInfo<>::FunctionContextSlotIndex(*scope_info, *name);
|
int index = scope_info->FunctionContextSlotIndex(*name);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
// slot found
|
// slot found
|
||||||
if (FLAG_trace_contexts) {
|
if (FLAG_trace_contexts) {
|
||||||
@ -216,18 +215,19 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
|
|||||||
ASSERT(context->is_function_context());
|
ASSERT(context->is_function_context());
|
||||||
|
|
||||||
// Check non-parameter locals.
|
// Check non-parameter locals.
|
||||||
Handle<Object> scope_info(context->closure()->shared()->scope_info());
|
Handle<SerializedScopeInfo> scope_info(
|
||||||
|
context->closure()->shared()->scope_info());
|
||||||
Variable::Mode mode;
|
Variable::Mode mode;
|
||||||
int index = ScopeInfo<>::ContextSlotIndex(*scope_info, *name, &mode);
|
int index = scope_info->ContextSlotIndex(*name, &mode);
|
||||||
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
|
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
|
||||||
if (index >= 0) return false;
|
if (index >= 0) return false;
|
||||||
|
|
||||||
// Check parameter locals.
|
// Check parameter locals.
|
||||||
int param_index = ScopeInfo<>::ParameterIndex(*scope_info, *name);
|
int param_index = scope_info->ParameterIndex(*name);
|
||||||
if (param_index >= 0) return false;
|
if (param_index >= 0) return false;
|
||||||
|
|
||||||
// Check context only holding the function name variable.
|
// Check context only holding the function name variable.
|
||||||
index = ScopeInfo<>::FunctionContextSlotIndex(*scope_info, *name);
|
index = scope_info->FunctionContextSlotIndex(*name);
|
||||||
if (index >= 0) return false;
|
if (index >= 0) return false;
|
||||||
context = Context::cast(context->closure()->context());
|
context = Context::cast(context->closure()->context());
|
||||||
}
|
}
|
||||||
|
@ -684,7 +684,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
|||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
int number_of_literals,
|
int number_of_literals,
|
||||||
Handle<Code> code,
|
Handle<Code> code,
|
||||||
Handle<Object> scope_info) {
|
Handle<SerializedScopeInfo> scope_info) {
|
||||||
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
|
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
|
||||||
shared->set_code(*code);
|
shared->set_code(*code);
|
||||||
shared->set_scope_info(*scope_info);
|
shared->set_scope_info(*scope_info);
|
||||||
|
@ -351,7 +351,7 @@ class Factory : public AllStatic {
|
|||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
int number_of_literals,
|
int number_of_literals,
|
||||||
Handle<Code> code,
|
Handle<Code> code,
|
||||||
Handle<Object> scope_info);
|
Handle<SerializedScopeInfo> scope_info);
|
||||||
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
|
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
|
||||||
|
|
||||||
static Handle<NumberDictionary> DictionaryAtNumberPut(
|
static Handle<NumberDictionary> DictionaryAtNumberPut(
|
||||||
|
@ -532,11 +532,11 @@ void JavaScriptFrame::Print(StringStream* accumulator,
|
|||||||
if (IsConstructor()) accumulator->Add("new ");
|
if (IsConstructor()) accumulator->Add("new ");
|
||||||
accumulator->PrintFunction(function, receiver, &code);
|
accumulator->PrintFunction(function, receiver, &code);
|
||||||
|
|
||||||
Handle<Object> scope_info(ScopeInfo<>::EmptyHeapObject());
|
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
|
||||||
|
|
||||||
if (function->IsJSFunction()) {
|
if (function->IsJSFunction()) {
|
||||||
Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
|
Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
|
||||||
scope_info = Handle<Object>(shared->scope_info());
|
scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
|
||||||
Object* script_obj = shared->script();
|
Object* script_obj = shared->script();
|
||||||
if (script_obj->IsScript()) {
|
if (script_obj->IsScript()) {
|
||||||
Handle<Script> script(Script::cast(script_obj));
|
Handle<Script> script(Script::cast(script_obj));
|
||||||
|
@ -326,6 +326,7 @@ class RegExpCompiler;
|
|||||||
class RegExpVisitor;
|
class RegExpVisitor;
|
||||||
class Scope;
|
class Scope;
|
||||||
template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
|
template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
|
||||||
|
class SerializedScopeInfo;
|
||||||
class Script;
|
class Script;
|
||||||
class Slot;
|
class Slot;
|
||||||
class Smi;
|
class Smi;
|
||||||
|
@ -2055,7 +2055,7 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
|
|||||||
share->set_name(name);
|
share->set_name(name);
|
||||||
Code* illegal = Builtins::builtin(Builtins::Illegal);
|
Code* illegal = Builtins::builtin(Builtins::Illegal);
|
||||||
share->set_code(illegal);
|
share->set_code(illegal);
|
||||||
share->set_scope_info(ScopeInfo<>::EmptyHeapObject());
|
share->set_scope_info(SerializedScopeInfo::Empty());
|
||||||
Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric);
|
Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric);
|
||||||
share->set_construct_stub(construct_stub);
|
share->set_construct_stub(construct_stub);
|
||||||
share->set_expected_nof_properties(0);
|
share->set_expected_nof_properties(0);
|
||||||
|
@ -2511,7 +2511,6 @@ ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
|
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
|
||||||
ACCESSORS(SharedFunctionInfo, scope_info, Object, kScopeInfoOffset)
|
|
||||||
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
|
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
|
||||||
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
|
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
|
||||||
kInstanceClassNameOffset)
|
kInstanceClassNameOffset)
|
||||||
@ -2648,6 +2647,19 @@ void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SerializedScopeInfo* SharedFunctionInfo::scope_info() {
|
||||||
|
return reinterpret_cast<SerializedScopeInfo*>(
|
||||||
|
READ_FIELD(this, kScopeInfoOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
|
||||||
|
WriteBarrierMode mode) {
|
||||||
|
WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
|
||||||
|
CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SharedFunctionInfo::is_compiled() {
|
bool SharedFunctionInfo::is_compiled() {
|
||||||
// TODO(1242782): Create a code kind for uncompiled code.
|
// TODO(1242782): Create a code kind for uncompiled code.
|
||||||
return code()->kind() != Code::STUB;
|
return code()->kind() != Code::STUB;
|
||||||
|
@ -3273,7 +3273,7 @@ class SharedFunctionInfo: public HeapObject {
|
|||||||
DECL_ACCESSORS(code, Code)
|
DECL_ACCESSORS(code, Code)
|
||||||
|
|
||||||
// [scope_info]: Scope info.
|
// [scope_info]: Scope info.
|
||||||
DECL_ACCESSORS(scope_info, Object)
|
DECL_ACCESSORS(scope_info, SerializedScopeInfo)
|
||||||
|
|
||||||
// [construct stub]: Code stub for constructing instances of this function.
|
// [construct stub]: Code stub for constructing instances of this function.
|
||||||
DECL_ACCESSORS(construct_stub, Code)
|
DECL_ACCESSORS(construct_stub, Code)
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
#include "scopeinfo.h"
|
||||||
#include "scopes.h"
|
#include "scopes.h"
|
||||||
#include "string-stream.h"
|
#include "string-stream.h"
|
||||||
|
|
||||||
@ -1968,8 +1969,9 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
|||||||
const int literals = fun->NumberOfLiterals();
|
const int literals = fun->NumberOfLiterals();
|
||||||
Handle<Code> code = Handle<Code>(fun->shared()->code());
|
Handle<Code> code = Handle<Code>(fun->shared()->code());
|
||||||
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
|
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
|
||||||
Handle<SharedFunctionInfo> shared = Factory::NewSharedFunctionInfo(
|
Handle<SharedFunctionInfo> shared =
|
||||||
name, literals, code, Handle<Object>(fun->shared()->scope_info()));
|
Factory::NewSharedFunctionInfo(name, literals, code,
|
||||||
|
Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
|
||||||
shared->set_construct_stub(*construct_stub);
|
shared->set_construct_stub(*construct_stub);
|
||||||
|
|
||||||
// Copy the function data to the shared function info.
|
// Copy the function data to the shared function info.
|
||||||
|
@ -1555,12 +1555,13 @@ void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
|
|||||||
JSFunction* func = JSFunction::cast(js_obj);
|
JSFunction* func = JSFunction::cast(js_obj);
|
||||||
Context* context = func->context();
|
Context* context = func->context();
|
||||||
ZoneScope zscope(DELETE_ON_EXIT);
|
ZoneScope zscope(DELETE_ON_EXIT);
|
||||||
Object* scope_info = context->closure()->shared()->scope_info();
|
SerializedScopeInfo* serialized_scope_info =
|
||||||
ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(scope_info);
|
context->closure()->shared()->scope_info();
|
||||||
|
ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info);
|
||||||
int locals_number = zone_scope_info.NumberOfLocals();
|
int locals_number = zone_scope_info.NumberOfLocals();
|
||||||
for (int i = 0; i < locals_number; ++i) {
|
for (int i = 0; i < locals_number; ++i) {
|
||||||
String* local_name = *zone_scope_info.LocalName(i);
|
String* local_name = *zone_scope_info.LocalName(i);
|
||||||
int idx = ScopeInfo<>::ContextSlotIndex(scope_info, local_name, NULL);
|
int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
|
||||||
if (idx >= 0 && idx < context->length()) {
|
if (idx >= 0 && idx < context->length()) {
|
||||||
snapshot_->SetClosureReference(entry, local_name, context->get(idx));
|
snapshot_->SetClosureReference(entry, local_name, context->get(idx));
|
||||||
}
|
}
|
||||||
|
@ -6869,8 +6869,7 @@ static Object* Runtime_NewContext(Arguments args) {
|
|||||||
ASSERT(args.length() == 1);
|
ASSERT(args.length() == 1);
|
||||||
|
|
||||||
CONVERT_CHECKED(JSFunction, function, args[0]);
|
CONVERT_CHECKED(JSFunction, function, args[0]);
|
||||||
int length =
|
int length = function->shared()->scope_info()->NumberOfContextSlots();
|
||||||
ScopeInfo<>::NumberOfContextSlots(function->shared()->scope_info());
|
|
||||||
Object* result = Heap::AllocateFunctionContext(length, function);
|
Object* result = Heap::AllocateFunctionContext(length, function);
|
||||||
if (result->IsFailure()) return result;
|
if (result->IsFailure()) return result;
|
||||||
|
|
||||||
@ -8492,7 +8491,7 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
|
|||||||
|
|
||||||
// Get scope info and read from it for local variable information.
|
// Get scope info and read from it for local variable information.
|
||||||
Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
|
Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
|
||||||
Handle<Object> scope_info(function->shared()->scope_info());
|
Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
|
||||||
ScopeInfo<> info(*scope_info);
|
ScopeInfo<> info(*scope_info);
|
||||||
|
|
||||||
// Get the context.
|
// Get the context.
|
||||||
@ -8521,9 +8520,7 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
|
|||||||
}
|
}
|
||||||
ASSERT(context->is_function_context());
|
ASSERT(context->is_function_context());
|
||||||
locals->set(i * 2 + 1,
|
locals->set(i * 2 + 1,
|
||||||
context->get(ScopeInfo<>::ContextSlotIndex(*scope_info,
|
context->get(scope_info->ContextSlotIndex(*name, NULL)));
|
||||||
*name,
|
|
||||||
NULL)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8663,7 +8660,8 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
|
|||||||
|
|
||||||
|
|
||||||
// Copy all the context locals into an object used to materialize a scope.
|
// Copy all the context locals into an object used to materialize a scope.
|
||||||
static void CopyContextLocalsToScopeObject(Handle<SharedFunctionInfo> shared,
|
static void CopyContextLocalsToScopeObject(
|
||||||
|
Handle<SerializedScopeInfo> serialized_scope_info,
|
||||||
ScopeInfo<>& scope_info,
|
ScopeInfo<>& scope_info,
|
||||||
Handle<Context> context,
|
Handle<Context> context,
|
||||||
Handle<JSObject> scope_object) {
|
Handle<JSObject> scope_object) {
|
||||||
@ -8671,10 +8669,8 @@ static void CopyContextLocalsToScopeObject(Handle<SharedFunctionInfo> shared,
|
|||||||
for (int i = Context::MIN_CONTEXT_SLOTS;
|
for (int i = Context::MIN_CONTEXT_SLOTS;
|
||||||
i < scope_info.number_of_context_slots();
|
i < scope_info.number_of_context_slots();
|
||||||
i++) {
|
i++) {
|
||||||
int context_index =
|
int context_index = serialized_scope_info->ContextSlotIndex(
|
||||||
ScopeInfo<>::ContextSlotIndex(shared->scope_info(),
|
*scope_info.context_slot_name(i), NULL);
|
||||||
*scope_info.context_slot_name(i),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
// Don't include the arguments shadow (.arguments) context variable.
|
// Don't include the arguments shadow (.arguments) context variable.
|
||||||
if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) {
|
if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) {
|
||||||
@ -8691,7 +8687,8 @@ static void CopyContextLocalsToScopeObject(Handle<SharedFunctionInfo> shared,
|
|||||||
static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
|
static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
|
||||||
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
||||||
Handle<SharedFunctionInfo> shared(function->shared());
|
Handle<SharedFunctionInfo> shared(function->shared());
|
||||||
ScopeInfo<> scope_info(shared->scope_info());
|
Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
|
||||||
|
ScopeInfo<> scope_info(*serialized_scope_info);
|
||||||
|
|
||||||
// Allocate and initialize a JSObject with all the arguments, stack locals
|
// Allocate and initialize a JSObject with all the arguments, stack locals
|
||||||
// heap locals and extension properties of the debugged function.
|
// heap locals and extension properties of the debugged function.
|
||||||
@ -8714,7 +8711,7 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
|
|||||||
// Third fill all context locals.
|
// Third fill all context locals.
|
||||||
Handle<Context> frame_context(Context::cast(frame->context()));
|
Handle<Context> frame_context(Context::cast(frame->context()));
|
||||||
Handle<Context> function_context(frame_context->fcontext());
|
Handle<Context> function_context(frame_context->fcontext());
|
||||||
CopyContextLocalsToScopeObject(shared, scope_info,
|
CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
|
||||||
function_context, local_scope);
|
function_context, local_scope);
|
||||||
|
|
||||||
// Finally copy any properties from the function context extension. This will
|
// Finally copy any properties from the function context extension. This will
|
||||||
@ -8742,7 +8739,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
|
|||||||
ASSERT(context->is_function_context());
|
ASSERT(context->is_function_context());
|
||||||
|
|
||||||
Handle<SharedFunctionInfo> shared(context->closure()->shared());
|
Handle<SharedFunctionInfo> shared(context->closure()->shared());
|
||||||
ScopeInfo<> scope_info(shared->scope_info());
|
Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
|
||||||
|
ScopeInfo<> scope_info(*serialized_scope_info);
|
||||||
|
|
||||||
// Allocate and initialize a JSObject with all the content of theis function
|
// Allocate and initialize a JSObject with all the content of theis function
|
||||||
// closure.
|
// closure.
|
||||||
@ -8750,8 +8748,7 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
|
|||||||
|
|
||||||
// Check whether the arguments shadow object exists.
|
// Check whether the arguments shadow object exists.
|
||||||
int arguments_shadow_index =
|
int arguments_shadow_index =
|
||||||
ScopeInfo<>::ContextSlotIndex(shared->scope_info(),
|
shared->scope_info()->ContextSlotIndex(Heap::arguments_shadow_symbol(),
|
||||||
Heap::arguments_shadow_symbol(),
|
|
||||||
NULL);
|
NULL);
|
||||||
if (arguments_shadow_index >= 0) {
|
if (arguments_shadow_index >= 0) {
|
||||||
// In this case all the arguments are available in the arguments shadow
|
// In this case all the arguments are available in the arguments shadow
|
||||||
@ -8766,7 +8763,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill all context locals to the context extension.
|
// Fill all context locals to the context extension.
|
||||||
CopyContextLocalsToScopeObject(shared, scope_info, context, closure_scope);
|
CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
|
||||||
|
context, closure_scope);
|
||||||
|
|
||||||
// Finally copy any properties from the function context extension. This will
|
// Finally copy any properties from the function context extension. This will
|
||||||
// be variables introduced by eval.
|
// be variables introduced by eval.
|
||||||
@ -8815,8 +8813,8 @@ class ScopeIterator {
|
|||||||
// created for evaluating top level code and it is not a real local scope.
|
// created for evaluating top level code and it is not a real local scope.
|
||||||
// Checking for the existence of .result seems fragile, but the scope info
|
// Checking for the existence of .result seems fragile, but the scope info
|
||||||
// saved with the code object does not otherwise have that information.
|
// saved with the code object does not otherwise have that information.
|
||||||
int index = ScopeInfo<>::StackSlotIndex(function_->shared()->scope_info(),
|
int index = function_->shared()->scope_info()->
|
||||||
Heap::result_symbol());
|
StackSlotIndex(Heap::result_symbol());
|
||||||
at_local_ = index < 0;
|
at_local_ = index < 0;
|
||||||
} else if (context_->is_function_context()) {
|
} else if (context_->is_function_context()) {
|
||||||
at_local_ = true;
|
at_local_ = true;
|
||||||
@ -9454,7 +9452,7 @@ static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
|
|||||||
// Runtime_DebugEvaluate.
|
// Runtime_DebugEvaluate.
|
||||||
static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
|
static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
|
||||||
Handle<JSFunction> function,
|
Handle<JSFunction> function,
|
||||||
Handle<Object> scope_info,
|
Handle<SerializedScopeInfo> scope_info,
|
||||||
const ScopeInfo<>* sinfo,
|
const ScopeInfo<>* sinfo,
|
||||||
Handle<Context> function_context) {
|
Handle<Context> function_context) {
|
||||||
// Try to find the value of 'arguments' to pass as parameter. If it is not
|
// Try to find the value of 'arguments' to pass as parameter. If it is not
|
||||||
@ -9462,15 +9460,14 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
|
|||||||
// does not support eval) then create an 'arguments' object.
|
// does not support eval) then create an 'arguments' object.
|
||||||
int index;
|
int index;
|
||||||
if (sinfo->number_of_stack_slots() > 0) {
|
if (sinfo->number_of_stack_slots() > 0) {
|
||||||
index = ScopeInfo<>::StackSlotIndex(*scope_info, Heap::arguments_symbol());
|
index = scope_info->StackSlotIndex(Heap::arguments_symbol());
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
return Handle<Object>(frame->GetExpression(index));
|
return Handle<Object>(frame->GetExpression(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
|
if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
|
||||||
index = ScopeInfo<>::ContextSlotIndex(*scope_info, Heap::arguments_symbol(),
|
index = scope_info->ContextSlotIndex(Heap::arguments_symbol(), NULL);
|
||||||
NULL);
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
return Handle<Object>(function_context->get(index));
|
return Handle<Object>(function_context->get(index));
|
||||||
}
|
}
|
||||||
@ -9521,7 +9518,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
|
|||||||
JavaScriptFrameIterator it(id);
|
JavaScriptFrameIterator it(id);
|
||||||
JavaScriptFrame* frame = it.frame();
|
JavaScriptFrame* frame = it.frame();
|
||||||
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
||||||
Handle<Object> scope_info(function->shared()->scope_info());
|
Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
|
||||||
ScopeInfo<> sinfo(*scope_info);
|
ScopeInfo<> sinfo(*scope_info);
|
||||||
|
|
||||||
// Traverse the saved contexts chain to find the active context for the
|
// Traverse the saved contexts chain to find the active context for the
|
||||||
|
407
src/scopeinfo.cc
407
src/scopeinfo.cc
@ -204,12 +204,6 @@ static inline Object** ReadSymbol(Object** p, Handle<String>* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline Object** ReadSentinel(Object** p) {
|
|
||||||
ASSERT(*p == NULL);
|
|
||||||
return p + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class Allocator>
|
template <class Allocator>
|
||||||
static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
|
static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
|
||||||
ASSERT(list->is_empty());
|
ASSERT(list->is_empty());
|
||||||
@ -220,7 +214,7 @@ static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
|
|||||||
p = ReadSymbol(p, &s);
|
p = ReadSymbol(p, &s);
|
||||||
list->Add(s);
|
list->Add(s);
|
||||||
}
|
}
|
||||||
return ReadSentinel(p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -239,42 +233,19 @@ static Object** ReadList(Object** p,
|
|||||||
list->Add(s);
|
list->Add(s);
|
||||||
modes->Add(static_cast<Variable::Mode>(m));
|
modes->Add(static_cast<Variable::Mode>(m));
|
||||||
}
|
}
|
||||||
return ReadSentinel(p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
Handle<Object> ScopeInfo<Allocator>::CreateHeapObject(Scope* scope) {
|
ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
|
||||||
ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
|
|
||||||
return sinfo.Serialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
Object* ScopeInfo<Allocator>::EmptyHeapObject() {
|
|
||||||
return Heap::empty_fixed_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline bool IsNotEmpty(Object* data) {
|
|
||||||
return FixedArray::cast(data)->length() != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline Object** GetDataStart(Object* data) {
|
|
||||||
return FixedArray::cast(data)->data_start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
ScopeInfo<Allocator>::ScopeInfo(Object* data)
|
|
||||||
: function_name_(Factory::empty_symbol()),
|
: function_name_(Factory::empty_symbol()),
|
||||||
parameters_(4),
|
parameters_(4),
|
||||||
stack_slots_(8),
|
stack_slots_(8),
|
||||||
context_slots_(8),
|
context_slots_(8),
|
||||||
context_modes_(8) {
|
context_modes_(8) {
|
||||||
if (IsNotEmpty(data)) {
|
if (data->length() > 0) {
|
||||||
Object** p0 = GetDataStart(data);
|
Object** p0 = data->data_start();
|
||||||
Object** p = p0;
|
Object** p = p0;
|
||||||
p = ReadSymbol(p, &function_name_);
|
p = ReadSymbol(p, &function_name_);
|
||||||
p = ReadBool(p, &calls_eval_);
|
p = ReadBool(p, &calls_eval_);
|
||||||
@ -304,12 +275,6 @@ static inline Object** WriteSymbol(Object** p, Handle<String> s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline Object** WriteSentinel(Object** p) {
|
|
||||||
*p++ = NULL;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class Allocator>
|
template <class Allocator>
|
||||||
static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
|
static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
|
||||||
const int n = list->length();
|
const int n = list->length();
|
||||||
@ -317,7 +282,7 @@ static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
|
|||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
p = WriteSymbol(p, list->at(i));
|
p = WriteSymbol(p, list->at(i));
|
||||||
}
|
}
|
||||||
return WriteSentinel(p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -331,23 +296,24 @@ static Object** WriteList(Object** p,
|
|||||||
p = WriteSymbol(p, list->at(i));
|
p = WriteSymbol(p, list->at(i));
|
||||||
p = WriteInt(p, modes->at(i));
|
p = WriteInt(p, modes->at(i));
|
||||||
}
|
}
|
||||||
return WriteSentinel(p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
Handle<Object> ScopeInfo<Allocator>::Serialize() {
|
Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
|
||||||
// function name, calls eval, length & sentinel for 3 tables:
|
// function name, calls eval, length for 3 tables:
|
||||||
const int extra_slots = 1 + 1 + 2 * 3;
|
const int extra_slots = 1 + 1 + 3;
|
||||||
int length = extra_slots +
|
int length = extra_slots +
|
||||||
context_slots_.length() * 2 +
|
context_slots_.length() * 2 +
|
||||||
parameters_.length() +
|
parameters_.length() +
|
||||||
stack_slots_.length();
|
stack_slots_.length();
|
||||||
|
|
||||||
Handle<Object> data(Factory::NewFixedArray(length, TENURED));
|
Handle<SerializedScopeInfo> data(
|
||||||
|
SerializedScopeInfo::cast(*Factory::NewFixedArray(length, TENURED)));
|
||||||
AssertNoAllocation nogc;
|
AssertNoAllocation nogc;
|
||||||
|
|
||||||
Object** p0 = GetDataStart(*data);
|
Object** p0 = data->data_start();
|
||||||
Object** p = p0;
|
Object** p = p0;
|
||||||
p = WriteSymbol(p, function_name_);
|
p = WriteSymbol(p, function_name_);
|
||||||
p = WriteBool(p, calls_eval_);
|
p = WriteBool(p, calls_eval_);
|
||||||
@ -360,185 +326,11 @@ Handle<Object> ScopeInfo<Allocator>::Serialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Object** ContextEntriesAddr(Object* data) {
|
|
||||||
ASSERT(IsNotEmpty(data));
|
|
||||||
// +2 for function name and calls eval:
|
|
||||||
return GetDataStart(data) + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Object** ParameterEntriesAddr(Object* data) {
|
|
||||||
ASSERT(IsNotEmpty(data));
|
|
||||||
Object** p = ContextEntriesAddr(data);
|
|
||||||
int n; // number of context slots;
|
|
||||||
p = ReadInt(p, &n);
|
|
||||||
return p + n*2 + 1; // *2 for pairs, +1 for sentinel
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static Object** StackSlotEntriesAddr(Object* data) {
|
|
||||||
ASSERT(IsNotEmpty(data));
|
|
||||||
Object** p = ParameterEntriesAddr(data);
|
|
||||||
int n; // number of parameter slots;
|
|
||||||
p = ReadInt(p, &n);
|
|
||||||
return p + n + 1; // +1 for sentinel
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
bool ScopeInfo<Allocator>::CallsEval(Object* data) {
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
// +1 for function name:
|
|
||||||
Object** p = GetDataStart(data) + 1;
|
|
||||||
bool calls_eval;
|
|
||||||
p = ReadBool(p, &calls_eval);
|
|
||||||
return calls_eval;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
int ScopeInfo<Allocator>::NumberOfStackSlots(Object* data) {
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
Object** p = StackSlotEntriesAddr(data);
|
|
||||||
int n; // number of stack slots;
|
|
||||||
ReadInt(p, &n);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
int ScopeInfo<Allocator>::NumberOfContextSlots(Object* data) {
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
Object** p = ContextEntriesAddr(data);
|
|
||||||
int n; // number of context slots;
|
|
||||||
ReadInt(p, &n);
|
|
||||||
return n + Context::MIN_CONTEXT_SLOTS;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
bool ScopeInfo<Allocator>::HasHeapAllocatedLocals(Object* data) {
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
Object** p = ContextEntriesAddr(data);
|
|
||||||
int n; // number of context slots;
|
|
||||||
ReadInt(p, &n);
|
|
||||||
return n > 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
int ScopeInfo<Allocator>::StackSlotIndex(Object* data, String* name) {
|
|
||||||
ASSERT(name->IsSymbol());
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
// Loop below depends on the NULL sentinel after the stack slot names.
|
|
||||||
ASSERT(NumberOfStackSlots(data) > 0 ||
|
|
||||||
*(StackSlotEntriesAddr(data) + 1) == NULL);
|
|
||||||
// slots start after length entry
|
|
||||||
Object** p0 = StackSlotEntriesAddr(data) + 1;
|
|
||||||
Object** p = p0;
|
|
||||||
while (*p != NULL) {
|
|
||||||
if (*p == name) return static_cast<int>(p - p0);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
int ScopeInfo<Allocator>::ContextSlotIndex(Object* data,
|
|
||||||
String* name,
|
|
||||||
Variable::Mode* mode) {
|
|
||||||
ASSERT(name->IsSymbol());
|
|
||||||
int result = ContextSlotCache::Lookup(data, name, mode);
|
|
||||||
if (result != ContextSlotCache::kNotFound) return result;
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
// Loop below depends on the NULL sentinel after the context slot names.
|
|
||||||
ASSERT(NumberOfContextSlots(data) >= Context::MIN_CONTEXT_SLOTS ||
|
|
||||||
*(ContextEntriesAddr(data) + 1) == NULL);
|
|
||||||
|
|
||||||
// slots start after length entry
|
|
||||||
Object** p0 = ContextEntriesAddr(data) + 1;
|
|
||||||
Object** p = p0;
|
|
||||||
// contexts may have no variable slots (in the presence of eval()).
|
|
||||||
while (*p != NULL) {
|
|
||||||
if (*p == name) {
|
|
||||||
ASSERT(((p - p0) & 1) == 0);
|
|
||||||
int v;
|
|
||||||
ReadInt(p + 1, &v);
|
|
||||||
Variable::Mode mode_value = static_cast<Variable::Mode>(v);
|
|
||||||
if (mode != NULL) *mode = mode_value;
|
|
||||||
result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
|
|
||||||
ContextSlotCache::Update(data, name, mode_value, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
p += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ContextSlotCache::Update(data, name, Variable::INTERNAL, -1);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
|
|
||||||
ASSERT(name->IsSymbol());
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
// We must read parameters from the end since for
|
|
||||||
// multiply declared parameters the value of the
|
|
||||||
// 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(data);
|
|
||||||
int n; // number of parameters
|
|
||||||
Object** p0 = ReadInt(p, &n);
|
|
||||||
p = p0 + n;
|
|
||||||
while (p > p0) {
|
|
||||||
p--;
|
|
||||||
if (*p == name) return static_cast<int>(p - p0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
int ScopeInfo<Allocator>::FunctionContextSlotIndex(Object* data, String* name) {
|
|
||||||
ASSERT(name->IsSymbol());
|
|
||||||
if (IsNotEmpty(data)) {
|
|
||||||
Object** p = GetDataStart(data);
|
|
||||||
if (*p == name) {
|
|
||||||
p = ContextEntriesAddr(data);
|
|
||||||
int n; // number of context slots
|
|
||||||
ReadInt(p, &n);
|
|
||||||
ASSERT(n != 0);
|
|
||||||
// The function context slot is the last entry.
|
|
||||||
return n + Context::MIN_CONTEXT_SLOTS - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
|
Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
|
||||||
// A local variable can be allocated either on the stack or in the context.
|
// 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 the
|
// For variables allocated in the context they are always preceded by
|
||||||
// number Context::MIN_CONTEXT_SLOTS number of fixed allocated slots in the
|
// Context::MIN_CONTEXT_SLOTS of fixed allocated slots in the context.
|
||||||
// context.
|
|
||||||
if (i < number_of_stack_slots()) {
|
if (i < number_of_stack_slots()) {
|
||||||
return stack_slot_name(i);
|
return stack_slot_name(i);
|
||||||
} else {
|
} else {
|
||||||
@ -559,6 +351,175 @@ int ScopeInfo<Allocator>::NumberOfLocals() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
return data_start() + 2; // +2 for function name and calls eval.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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() {
|
||||||
|
if (length() > 0) {
|
||||||
|
Object** p = data_start() + 1; // +1 for function name.
|
||||||
|
bool calls_eval;
|
||||||
|
p = ReadBool(p, &calls_eval);
|
||||||
|
return calls_eval;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SerializedScopeInfo::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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
|
||||||
|
ASSERT(name->IsSymbol());
|
||||||
|
int result = ContextSlotCache::Lookup(this, name, mode);
|
||||||
|
if (result != ContextSlotCache::kNotFound) return result;
|
||||||
|
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);
|
||||||
|
Variable::Mode mode_value = static_cast<Variable::Mode>(v);
|
||||||
|
if (mode != NULL) *mode = mode_value;
|
||||||
|
result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
|
||||||
|
ContextSlotCache::Update(this, name, mode_value, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
p += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContextSlotCache::Update(this, name, Variable::INTERNAL, -1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SerializedScopeInfo::ParameterIndex(String* name) {
|
||||||
|
ASSERT(name->IsSymbol());
|
||||||
|
if (length() > 0) {
|
||||||
|
// We must read parameters from the end since for
|
||||||
|
// multiply declared parameters the value of the
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SerializedScopeInfo::FunctionContextSlotIndex(String* name) {
|
||||||
|
ASSERT(name->IsSymbol());
|
||||||
|
if (length() > 0) {
|
||||||
|
Object** p = data_start();
|
||||||
|
if (*p == name) {
|
||||||
|
p = ContextEntriesAddr();
|
||||||
|
int number_of_context_slots;
|
||||||
|
ReadInt(p, &number_of_context_slots);
|
||||||
|
ASSERT(number_of_context_slots != 0);
|
||||||
|
// The function context slot is the last entry.
|
||||||
|
return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ContextSlotCache::Hash(Object* data, String* name) {
|
int ContextSlotCache::Hash(Object* data, String* name) {
|
||||||
// Uses only lower 32 bits if pointers are larger.
|
// Uses only lower 32 bits if pointers are larger.
|
||||||
uintptr_t addr_hash =
|
uintptr_t addr_hash =
|
||||||
|
119
src/scopeinfo.h
119
src/scopeinfo.h
@ -54,16 +54,11 @@ class ScopeInfo BASE_EMBEDDED {
|
|||||||
// Create a ScopeInfo instance from a scope.
|
// Create a ScopeInfo instance from a scope.
|
||||||
explicit ScopeInfo(Scope* scope);
|
explicit ScopeInfo(Scope* scope);
|
||||||
|
|
||||||
// Create a ScopeInfo instance from an Object holding the serialized data.
|
// Create a ScopeInfo instance from SerializedScopeInfo.
|
||||||
explicit ScopeInfo(Object* data);
|
explicit ScopeInfo(SerializedScopeInfo* data);
|
||||||
|
|
||||||
// Creates a heap object holding the serialized scope info.
|
// Creates a SerializedScopeInfo holding the serialized scope info.
|
||||||
Handle<Object> Serialize();
|
Handle<SerializedScopeInfo> Serialize();
|
||||||
|
|
||||||
static Handle<Object> CreateHeapObject(Scope* scope);
|
|
||||||
|
|
||||||
// Serializes empty scope info.
|
|
||||||
static Object* EmptyHeapObject();
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Lookup
|
// Lookup
|
||||||
@ -87,51 +82,6 @@ class ScopeInfo BASE_EMBEDDED {
|
|||||||
Handle<String> LocalName(int i) const;
|
Handle<String> LocalName(int i) const;
|
||||||
int NumberOfLocals() const;
|
int NumberOfLocals() const;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// The following functions provide quick access to scope info details
|
|
||||||
// for runtime routines w/o the need to explicitly create a ScopeInfo
|
|
||||||
// object.
|
|
||||||
//
|
|
||||||
// ScopeInfo is the only class which should have to know about the
|
|
||||||
// encoding of it's information in a FixedArray object, which is why these
|
|
||||||
// functions are in this class.
|
|
||||||
|
|
||||||
// Does this scope call eval.
|
|
||||||
static bool CallsEval(Object* data);
|
|
||||||
|
|
||||||
// Return the number of stack slots for code.
|
|
||||||
static int NumberOfStackSlots(Object* data);
|
|
||||||
|
|
||||||
// Return the number of context slots for code.
|
|
||||||
static int NumberOfContextSlots(Object* data);
|
|
||||||
|
|
||||||
// Return if this has context slots besides MIN_CONTEXT_SLOTS;
|
|
||||||
static bool HasHeapAllocatedLocals(Object* data);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
// (canonicalized).
|
|
||||||
static int StackSlotIndex(Object* data, String* name);
|
|
||||||
|
|
||||||
// Lookup support for serialized scope info. Returns the
|
|
||||||
// context slot index for a given slot name if the slot is present; otherwise
|
|
||||||
// returns a value < 0. The name must be a symbol (canonicalized).
|
|
||||||
// If the slot is present and mode != NULL, sets *mode to the corresponding
|
|
||||||
// mode for that variable.
|
|
||||||
static int ContextSlotIndex(Object* data, String* name, Variable::Mode* mode);
|
|
||||||
|
|
||||||
// Lookup support for serialized scope info. Returns the
|
|
||||||
// parameter index for a given parameter name if the parameter is present;
|
|
||||||
// otherwise returns a value < 0. The name must be a symbol (canonicalized).
|
|
||||||
static int ParameterIndex(Object* data, String* name);
|
|
||||||
|
|
||||||
// Lookup support for serialized scope info. Returns the
|
|
||||||
// function context slot index if the function name is present (named
|
|
||||||
// function expressions, only), otherwise returns a value < 0. The name
|
|
||||||
// must be a symbol (canonicalized).
|
|
||||||
static int FunctionContextSlotIndex(Object* data, String* name);
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// Debugging support
|
// Debugging support
|
||||||
|
|
||||||
@ -149,6 +99,67 @@ class ScopeInfo BASE_EMBEDDED {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 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->IsFixedArray());
|
||||||
|
return reinterpret_cast<SerializedScopeInfo*>(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does this scope call eval.
|
||||||
|
bool CallsEval();
|
||||||
|
|
||||||
|
// Return the number of stack slots for code.
|
||||||
|
int NumberOfStackSlots();
|
||||||
|
|
||||||
|
// Return the number of context slots for code.
|
||||||
|
int NumberOfContextSlots();
|
||||||
|
|
||||||
|
// Return if this has context slots besides MIN_CONTEXT_SLOTS;
|
||||||
|
bool HasHeapAllocatedLocals();
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// (canonicalized).
|
||||||
|
int StackSlotIndex(String* name);
|
||||||
|
|
||||||
|
// Lookup support for serialized scope info. Returns the
|
||||||
|
// context slot index for a given slot name if the slot is present; otherwise
|
||||||
|
// returns a value < 0. The name must be a symbol (canonicalized).
|
||||||
|
// If the slot is present and mode != NULL, sets *mode to the corresponding
|
||||||
|
// mode for that variable.
|
||||||
|
int ContextSlotIndex(String* name, Variable::Mode* mode);
|
||||||
|
|
||||||
|
// Lookup support for serialized scope info. Returns the
|
||||||
|
// parameter index for a given parameter name if the parameter is present;
|
||||||
|
// otherwise returns a value < 0. The name must be a symbol (canonicalized).
|
||||||
|
int ParameterIndex(String* name);
|
||||||
|
|
||||||
|
// Lookup support for serialized scope info. Returns the
|
||||||
|
// function context slot index if the function name is present (named
|
||||||
|
// function expressions, only), otherwise returns a value < 0. The name
|
||||||
|
// must be a symbol (canonicalized).
|
||||||
|
int FunctionContextSlotIndex(String* name);
|
||||||
|
|
||||||
|
static Handle<SerializedScopeInfo> Create(Scope* scope);
|
||||||
|
|
||||||
|
// Serializes empty scope info.
|
||||||
|
static SerializedScopeInfo* Empty();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
inline Object** ContextEntriesAddr();
|
||||||
|
|
||||||
|
inline Object** ParameterEntriesAddr();
|
||||||
|
|
||||||
|
inline Object** StackSlotEntriesAddr();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Cache for mapping (data, property name) into context slot index.
|
// Cache for mapping (data, property name) into context slot index.
|
||||||
// The cache contains both positive and negative results.
|
// The cache contains both positive and negative results.
|
||||||
// Slot index equals -1 means the property is absent.
|
// Slot index equals -1 means the property is absent.
|
||||||
|
Loading…
Reference in New Issue
Block a user