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
parent 3bc97b7d
......@@ -549,8 +549,8 @@ Object* Accessors::FunctionGetArguments(Object* object, void*) {
if (frame->function() != *function) continue;
// If there is an arguments variable in the stack, we return that.
int index = ScopeInfo<>::StackSlotIndex(function->shared()->scope_info(),
Heap::arguments_symbol());
int index = function->shared()->scope_info()->
StackSlotIndex(Heap::arguments_symbol());
if (index >= 0) {
Handle<Object> arguments = Handle<Object>(frame->GetExpression(index));
if (!arguments->IsTheHole()) return *arguments;
......
......@@ -160,7 +160,7 @@ Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
Handle<Code> code = MakeCode(context, info);
if (!info->shared_info().is_null()) {
info->shared_info()->set_scope_info(
*ScopeInfo<>::CreateHeapObject(info->scope()));
*SerializedScopeInfo::Create(info->scope()));
}
return code;
}
......@@ -262,7 +262,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
lit->name(),
lit->materialized_literal_count(),
code,
ScopeInfo<>::CreateHeapObject(info.scope()));
SerializedScopeInfo::Create(info.scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
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.
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.
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
......@@ -485,7 +485,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive();
Handle<Object> scope_info(ScopeInfo<>::EmptyHeapObject());
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
// Generate code
Handle<Code> code;
......@@ -568,7 +568,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
literal->start_position(),
script,
code);
scope_info = ScopeInfo<>::CreateHeapObject(info.scope());
scope_info = SerializedScopeInfo::Create(info.scope());
}
// Create a shared function info object.
......
......@@ -120,9 +120,10 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
// we have context-local slots
// 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;
int index = ScopeInfo<>::ContextSlotIndex(*scope_info, *name, &mode);
int index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (index >= 0) {
// slot found
......@@ -150,13 +151,11 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
// check parameter locals in context
int param_index = ScopeInfo<>::ParameterIndex(*scope_info, *name);
int param_index = scope_info->ParameterIndex(*name);
if (param_index >= 0) {
// slot found.
int index =
ScopeInfo<>::ContextSlotIndex(*scope_info,
Heap::arguments_shadow_symbol(),
NULL);
scope_info->ContextSlotIndex(Heap::arguments_shadow_symbol(), NULL);
ASSERT(index >= 0); // arguments must exist and be in the heap context
Handle<JSObject> arguments(JSObject::cast(context->get(index)));
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)
if (follow_context_chain) {
int index = ScopeInfo<>::FunctionContextSlotIndex(*scope_info, *name);
int index = scope_info->FunctionContextSlotIndex(*name);
if (index >= 0) {
// slot found
if (FLAG_trace_contexts) {
......@@ -216,18 +215,19 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
ASSERT(context->is_function_context());
// 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;
int index = ScopeInfo<>::ContextSlotIndex(*scope_info, *name, &mode);
int index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (index >= 0) return false;
// Check parameter locals.
int param_index = ScopeInfo<>::ParameterIndex(*scope_info, *name);
int param_index = scope_info->ParameterIndex(*name);
if (param_index >= 0) return false;
// Check context only holding the function name variable.
index = ScopeInfo<>::FunctionContextSlotIndex(*scope_info, *name);
index = scope_info->FunctionContextSlotIndex(*name);
if (index >= 0) return false;
context = Context::cast(context->closure()->context());
}
......
......@@ -684,7 +684,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name,
int number_of_literals,
Handle<Code> code,
Handle<Object> scope_info) {
Handle<SerializedScopeInfo> scope_info) {
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
shared->set_code(*code);
shared->set_scope_info(*scope_info);
......
......@@ -351,7 +351,7 @@ class Factory : public AllStatic {
Handle<String> name,
int number_of_literals,
Handle<Code> code,
Handle<Object> scope_info);
Handle<SerializedScopeInfo> scope_info);
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
static Handle<NumberDictionary> DictionaryAtNumberPut(
......
......@@ -532,11 +532,11 @@ void JavaScriptFrame::Print(StringStream* accumulator,
if (IsConstructor()) accumulator->Add("new ");
accumulator->PrintFunction(function, receiver, &code);
Handle<Object> scope_info(ScopeInfo<>::EmptyHeapObject());
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
if (function->IsJSFunction()) {
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();
if (script_obj->IsScript()) {
Handle<Script> script(Script::cast(script_obj));
......
......@@ -326,6 +326,7 @@ class RegExpCompiler;
class RegExpVisitor;
class Scope;
template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
class SerializedScopeInfo;
class Script;
class Slot;
class Smi;
......
......@@ -2055,7 +2055,7 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
share->set_name(name);
Code* illegal = Builtins::builtin(Builtins::Illegal);
share->set_code(illegal);
share->set_scope_info(ScopeInfo<>::EmptyHeapObject());
share->set_scope_info(SerializedScopeInfo::Empty());
Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric);
share->set_construct_stub(construct_stub);
share->set_expected_nof_properties(0);
......
......@@ -2511,7 +2511,6 @@ ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
#endif
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
ACCESSORS(SharedFunctionInfo, scope_info, Object, kScopeInfoOffset)
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
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() {
// TODO(1242782): Create a code kind for uncompiled code.
return code()->kind() != Code::STUB;
......
......@@ -3273,7 +3273,7 @@ class SharedFunctionInfo: public HeapObject {
DECL_ACCESSORS(code, Code)
// [scope_info]: Scope info.
DECL_ACCESSORS(scope_info, Object)
DECL_ACCESSORS(scope_info, SerializedScopeInfo)
// [construct stub]: Code stub for constructing instances of this function.
DECL_ACCESSORS(construct_stub, Code)
......
......@@ -36,6 +36,7 @@
#include "parser.h"
#include "platform.h"
#include "runtime.h"
#include "scopeinfo.h"
#include "scopes.h"
#include "string-stream.h"
......@@ -1968,8 +1969,9 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
const int literals = fun->NumberOfLiterals();
Handle<Code> code = Handle<Code>(fun->shared()->code());
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
Handle<SharedFunctionInfo> shared = Factory::NewSharedFunctionInfo(
name, literals, code, Handle<Object>(fun->shared()->scope_info()));
Handle<SharedFunctionInfo> shared =
Factory::NewSharedFunctionInfo(name, literals, code,
Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
shared->set_construct_stub(*construct_stub);
// 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);
Context* context = func->context();
ZoneScope zscope(DELETE_ON_EXIT);
Object* scope_info = context->closure()->shared()->scope_info();
ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(scope_info);
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 = ScopeInfo<>::ContextSlotIndex(scope_info, local_name, NULL);
int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
if (idx >= 0 && idx < context->length()) {
snapshot_->SetClosureReference(entry, local_name, context->get(idx));
}
......
......@@ -6869,8 +6869,7 @@ static Object* Runtime_NewContext(Arguments args) {
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSFunction, function, args[0]);
int length =
ScopeInfo<>::NumberOfContextSlots(function->shared()->scope_info());
int length = function->shared()->scope_info()->NumberOfContextSlots();
Object* result = Heap::AllocateFunctionContext(length, function);
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.
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);
// Get the context.
......@@ -8521,9 +8520,7 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
}
ASSERT(context->is_function_context());
locals->set(i * 2 + 1,
context->get(ScopeInfo<>::ContextSlotIndex(*scope_info,
*name,
NULL)));
context->get(scope_info->ContextSlotIndex(*name, NULL)));
}
}
......@@ -8663,18 +8660,17 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
// Copy all the context locals into an object used to materialize a scope.
static void CopyContextLocalsToScopeObject(Handle<SharedFunctionInfo> shared,
ScopeInfo<>& scope_info,
Handle<Context> context,
Handle<JSObject> scope_object) {
static void CopyContextLocalsToScopeObject(
Handle<SerializedScopeInfo> serialized_scope_info,
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 =
ScopeInfo<>::ContextSlotIndex(shared->scope_info(),
*scope_info.context_slot_name(i),
NULL);
int context_index = serialized_scope_info->ContextSlotIndex(
*scope_info.context_slot_name(i), NULL);
// Don't include the arguments shadow (.arguments) context variable.
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) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
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
// heap locals and extension properties of the debugged function.
......@@ -8714,7 +8711,7 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
// Third fill all context locals.
Handle<Context> frame_context(Context::cast(frame->context()));
Handle<Context> function_context(frame_context->fcontext());
CopyContextLocalsToScopeObject(shared, scope_info,
CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
function_context, local_scope);
// 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());
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
// closure.
......@@ -8750,9 +8748,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
// Check whether the arguments shadow object exists.
int arguments_shadow_index =
ScopeInfo<>::ContextSlotIndex(shared->scope_info(),
Heap::arguments_shadow_symbol(),
NULL);
shared->scope_info()->ContextSlotIndex(Heap::arguments_shadow_symbol(),
NULL);
if (arguments_shadow_index >= 0) {
// In this case all the arguments are available in the arguments shadow
// object.
......@@ -8766,7 +8763,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
}
// 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
// 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.
// Checking for the existence of .result seems fragile, but the scope info
// saved with the code object does not otherwise have that information.
int index = ScopeInfo<>::StackSlotIndex(function_->shared()->scope_info(),
Heap::result_symbol());
int index = function_->shared()->scope_info()->
StackSlotIndex(Heap::result_symbol());
at_local_ = index < 0;
} else if (context_->is_function_context()) {
at_local_ = true;
......@@ -9454,7 +9452,7 @@ static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
// Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
Handle<JSFunction> function,
Handle<Object> scope_info,
Handle<SerializedScopeInfo> scope_info,
const ScopeInfo<>* sinfo,
Handle<Context> function_context) {
// 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.
int index;
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) {
return Handle<Object>(frame->GetExpression(index));
}
}
if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
index = ScopeInfo<>::ContextSlotIndex(*scope_info, Heap::arguments_symbol(),
NULL);
index = scope_info->ContextSlotIndex(Heap::arguments_symbol(), NULL);
if (index != -1) {
return Handle<Object>(function_context->get(index));
}
......@@ -9521,7 +9518,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
JavaScriptFrameIterator it(id);
JavaScriptFrame* frame = it.frame();
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);
// Traverse the saved contexts chain to find the active context for the
......
This diff is collapsed.
......@@ -54,16 +54,11 @@ class ScopeInfo BASE_EMBEDDED {
// Create a ScopeInfo instance from a scope.
explicit ScopeInfo(Scope* scope);
// Create a ScopeInfo instance from an Object holding the serialized data.
explicit ScopeInfo(Object* data);
// Create a ScopeInfo instance from SerializedScopeInfo.
explicit ScopeInfo(SerializedScopeInfo* data);
// Creates a heap object holding the serialized scope info.
Handle<Object> Serialize();
static Handle<Object> CreateHeapObject(Scope* scope);
// Serializes empty scope info.
static Object* EmptyHeapObject();
// Creates a SerializedScopeInfo holding the serialized scope info.
Handle<SerializedScopeInfo> Serialize();
// --------------------------------------------------------------------------
// Lookup
......@@ -88,64 +83,80 @@ class ScopeInfo BASE_EMBEDDED {
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.
// Debugging support
#ifdef DEBUG
void Print();
#endif
private:
Handle<String> function_name_;
bool calls_eval_;
List<Handle<String>, Allocator > parameters_;
List<Handle<String>, Allocator > stack_slots_;
List<Handle<String>, Allocator > context_slots_;
List<Variable::Mode, Allocator > context_modes_;
};
// 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.
static bool CallsEval(Object* data);
bool CallsEval();
// Return the number of stack slots for code.
static int NumberOfStackSlots(Object* data);
int NumberOfStackSlots();
// Return the number of context slots for code.
static int NumberOfContextSlots(Object* data);
int NumberOfContextSlots();
// Return if this has context slots besides MIN_CONTEXT_SLOTS;
static bool HasHeapAllocatedLocals(Object* data);
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).
static int StackSlotIndex(Object* data, String* name);
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.
static int ContextSlotIndex(Object* data, String* name, Variable::Mode* mode);
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).
static int ParameterIndex(Object* data, String* name);
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).
static int FunctionContextSlotIndex(Object* data, String* name);
int FunctionContextSlotIndex(String* name);
// --------------------------------------------------------------------------
// Debugging support
static Handle<SerializedScopeInfo> Create(Scope* scope);
#ifdef DEBUG
void Print();
#endif
// Serializes empty scope info.
static SerializedScopeInfo* Empty();
private:
Handle<String> function_name_;
bool calls_eval_;
List<Handle<String>, Allocator > parameters_;
List<Handle<String>, Allocator > stack_slots_;
List<Handle<String>, Allocator > context_slots_;
List<Variable::Mode, Allocator > context_modes_;
inline Object** ContextEntriesAddr();
inline Object** ParameterEntriesAddr();
inline Object** StackSlotEntriesAddr();
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment