Revision: 5067
Author: [email protected]
Date: Wed Jul 14 04:18:09 2010
Log: 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
http://code.google.com/p/v8/source/detail?r=5067

Modified:
 /branches/bleeding_edge/src/accessors.cc
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/contexts.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/frames.cc
 /branches/bleeding_edge/src/globals.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/runtime.cc
 /branches/bleeding_edge/src/scopeinfo.cc
 /branches/bleeding_edge/src/scopeinfo.h

=======================================
--- /branches/bleeding_edge/src/accessors.cc    Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/accessors.cc    Wed Jul 14 04:18:09 2010
@@ -549,8 +549,8 @@
     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;
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/compiler.cc     Wed Jul 14 04:18:09 2010
@@ -160,7 +160,7 @@
   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 @@
           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 @@

// 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 @@
   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 @@
                               literal->start_position(),
                               script,
                               code);
-    scope_info = ScopeInfo<>::CreateHeapObject(info.scope());
+    scope_info = SerializedScopeInfo::Create(info.scope());
   }

   // Create a shared function info object.
=======================================
--- /branches/bleeding_edge/src/contexts.cc     Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/contexts.cc     Wed Jul 14 04:18:09 2010
@@ -120,9 +120,10 @@
       // 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 @@
       }

       // 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 @@

// 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 @@
     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());
   }
=======================================
--- /branches/bleeding_edge/src/factory.cc      Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/factory.cc      Wed Jul 14 04:18:09 2010
@@ -684,7 +684,7 @@
     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);
=======================================
--- /branches/bleeding_edge/src/factory.h       Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/factory.h       Wed Jul 14 04:18:09 2010
@@ -351,7 +351,7 @@
       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(
=======================================
--- /branches/bleeding_edge/src/frames.cc       Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/frames.cc       Wed Jul 14 04:18:09 2010
@@ -532,11 +532,11 @@
   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));
=======================================
--- /branches/bleeding_edge/src/globals.h       Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/globals.h       Wed Jul 14 04:18:09 2010
@@ -326,6 +326,7 @@
 class RegExpVisitor;
 class Scope;
 template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
+class SerializedScopeInfo;
 class Script;
 class Slot;
 class Smi;
=======================================
--- /branches/bleeding_edge/src/heap.cc Wed Jul 14 02:45:08 2010
+++ /branches/bleeding_edge/src/heap.cc Wed Jul 14 04:18:09 2010
@@ -2055,7 +2055,7 @@
   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);
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/objects-inl.h   Wed Jul 14 04:18:09 2010
@@ -2511,7 +2511,6 @@
 #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)
@@ -2646,6 +2645,19 @@
   WRITE_FIELD(this, kCodeOffset, value);
   CONDITIONAL_WRITE_BARRIER(this, kCodeOffset, 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() {
=======================================
--- /branches/bleeding_edge/src/objects.h       Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/objects.h       Wed Jul 14 04:18:09 2010
@@ -3273,7 +3273,7 @@
   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)
=======================================
--- /branches/bleeding_edge/src/parser.cc       Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/parser.cc       Wed Jul 14 04:18:09 2010
@@ -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 @@
   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.
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Jul 13 06:06:33 2010 +++ /branches/bleeding_edge/src/profile-generator.cc Wed Jul 14 04:18:09 2010
@@ -1555,12 +1555,13 @@
     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));
       }
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/runtime.cc      Wed Jul 14 04:18:09 2010
@@ -6869,8 +6869,7 @@
   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 @@

   // 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 @@
       }
       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 @@


 // 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 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 @@
   // 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 @@
   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 @@

   // 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 @@
   }

   // 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 @@
// 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 @@
 // 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 @@
   // 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 @@
   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
=======================================
--- /branches/bleeding_edge/src/scopeinfo.cc    Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/scopeinfo.cc    Wed Jul 14 04:18:09 2010
@@ -202,12 +202,6 @@
   *s = Handle<String>(reinterpret_cast<String*>(*p++));
   return p;
 }
-
-
-static inline Object** ReadSentinel(Object** p) {
-  ASSERT(*p == NULL);
-  return p + 1;
-}


 template <class Allocator>
@@ -220,7 +214,7 @@
     p = ReadSymbol(p, &s);
     list->Add(s);
   }
-  return ReadSentinel(p);
+  return p;
 }


@@ -239,42 +233,19 @@
     list->Add(s);
     modes->Add(static_cast<Variable::Mode>(m));
   }
-  return ReadSentinel(p);
+  return p;
 }


 template<class Allocator>
-Handle<Object> ScopeInfo<Allocator>::CreateHeapObject(Scope* scope) {
-  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)
+ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
   : function_name_(Factory::empty_symbol()),
     parameters_(4),
     stack_slots_(8),
     context_slots_(8),
     context_modes_(8) {
-  if (IsNotEmpty(data)) {
-    Object** p0 = GetDataStart(data);
+  if (data->length() > 0) {
+    Object** p0 = data->data_start();
     Object** p = p0;
     p = ReadSymbol(p, &function_name_);
     p = ReadBool(p, &calls_eval_);
@@ -302,12 +273,6 @@
   *p++ = *s;
   return p;
 }
-
-
-static inline Object** WriteSentinel(Object** p) {
-  *p++ = NULL;
-  return p;
-}


 template <class Allocator>
@@ -317,7 +282,7 @@
   for (int i = 0; i < n; i++) {
     p = WriteSymbol(p, list->at(i));
   }
-  return WriteSentinel(p);
+  return p;
 }


@@ -331,23 +296,24 @@
     p = WriteSymbol(p, list->at(i));
     p = WriteInt(p, modes->at(i));
   }
-  return WriteSentinel(p);
+  return p;
 }


 template<class Allocator>
-Handle<Object> ScopeInfo<Allocator>::Serialize() {
-  // function name, calls eval, length & sentinel for 3 tables:
-  const int extra_slots = 1 + 1 + 2 * 3;
+Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
+  // function name, calls eval, length for 3 tables:
+  const int extra_slots = 1 + 1 + 3;
   int length = extra_slots +
                context_slots_.length() * 2 +
                parameters_.length() +
                stack_slots_.length();

-  Handle<Object> data(Factory::NewFixedArray(length, TENURED));
+  Handle<SerializedScopeInfo> data(
+      SerializedScopeInfo::cast(*Factory::NewFixedArray(length, TENURED)));
   AssertNoAllocation nogc;

-  Object** p0 = GetDataStart(*data);
+  Object** p0 = data->data_start();
   Object** p = p0;
   p = WriteSymbol(p, function_name_);
   p = WriteBool(p, calls_eval_);
@@ -360,36 +326,69 @@
 }


-static Object** ContextEntriesAddr(Object* data) {
-  ASSERT(IsNotEmpty(data));
-  // +2 for function name and calls eval:
-  return GetDataStart(data) + 2;
+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);
+  } else {
+    return context_slot_name(i - number_of_stack_slots() +
+                             Context::MIN_CONTEXT_SLOTS);
+  }
 }


-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
+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;
+  }
+  return number_of_locals;
 }


-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
+Handle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) {
+  ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
+  return sinfo.Serialize();
 }


-template<class Allocator>
-bool ScopeInfo<Allocator>::CallsEval(Object* data) {
-  if (IsNotEmpty(data)) {
-    // +1 for function name:
-    Object** p = GetDataStart(data) + 1;
+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;
@@ -398,53 +397,49 @@
 }


-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;
+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;
 }


-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;
+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;
 }


-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;
+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;
 }


-template<class Allocator>
-int ScopeInfo<Allocator>::StackSlotIndex(Object* data, String* name) {
+int SerializedScopeInfo::StackSlotIndex(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;
+  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;
-    while (*p != NULL) {
+    Object** end = p0 + number_of_stack_slots;
+    while (p != end) {
       if (*p == name) return static_cast<int>(p - p0);
       p++;
     }
@@ -452,24 +447,18 @@
   return -1;
 }

-
-template<class Allocator>
-int ScopeInfo<Allocator>::ContextSlotIndex(Object* data,
-                                           String* name,
-                                           Variable::Mode* mode) {
+int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
   ASSERT(name->IsSymbol());
-  int result = ContextSlotCache::Lookup(data, name, mode);
+  int result = ContextSlotCache::Lookup(this, 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;
+  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;
-    // contexts may have no variable slots (in the presence of eval()).
-    while (*p != NULL) {
+    Object** end = p0 + number_of_context_slots * 2;
+    while (p != end) {
       if (*p == name) {
         ASSERT(((p - p0) & 1) == 0);
         int v;
@@ -477,21 +466,20 @@
         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);
+        ContextSlotCache::Update(this, name, mode_value, result);
         return result;
       }
       p += 2;
     }
   }
-  ContextSlotCache::Update(data, name, Variable::INTERNAL, -1);
+  ContextSlotCache::Update(this, name, Variable::INTERNAL, -1);
   return -1;
 }


-template<class Allocator>
-int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
+int SerializedScopeInfo::ParameterIndex(String* name) {
   ASSERT(name->IsSymbol());
-  if (IsNotEmpty(data)) {
+  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
@@ -502,10 +490,10 @@
     // 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;
+    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);
@@ -515,48 +503,21 @@
 }


-template<class Allocator>
-int ScopeInfo<Allocator>::FunctionContextSlotIndex(Object* data, String* name) {
+int SerializedScopeInfo::FunctionContextSlotIndex(String* name) {
   ASSERT(name->IsSymbol());
-  if (IsNotEmpty(data)) {
-    Object** p = GetDataStart(data);
+  if (length() > 0) {
+    Object** p = data_start();
     if (*p == name) {
-      p = ContextEntriesAddr(data);
-      int n;  // number of context slots
-      ReadInt(p, &n);
-      ASSERT(n != 0);
+      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 n + Context::MIN_CONTEXT_SLOTS - 1;
+      return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
     }
   }
   return -1;
 }
-
-
-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 the
- // number Context::MIN_CONTEXT_SLOTS number of fixed allocated slots in the
-  // context.
-  if (i < number_of_stack_slots()) {
-    return stack_slot_name(i);
-  } else {
-    return context_slot_name(i - number_of_stack_slots() +
-                             Context::MIN_CONTEXT_SLOTS);
-  }
-}
-
-
-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;
-  }
-  return number_of_locals;
-}


 int ContextSlotCache::Hash(Object* data, String* name) {
=======================================
--- /branches/bleeding_edge/src/scopeinfo.h     Tue Jul 13 06:06:33 2010
+++ /branches/bleeding_edge/src/scopeinfo.h     Wed Jul 14 04:18:09 2010
@@ -54,16 +54,11 @@
   // 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);
-
-  // 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();
+  // Create a ScopeInfo instance from SerializedScopeInfo.
+  explicit ScopeInfo(SerializedScopeInfo* data);
+
+  // Creates a SerializedScopeInfo holding the serialized scope info.
+  Handle<SerializedScopeInfo> Serialize();

// --------------------------------------------------------------------------
   // Lookup
@@ -88,64 +83,80 @@
   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);
-
- // --------------------------------------------------------------------------
-  // Debugging support
-
-#ifdef DEBUG
-  void Print();
-#endif
+  int FunctionContextSlotIndex(String* name);
+
+  static Handle<SerializedScopeInfo> Create(Scope* scope);
+
+  // 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();
 };


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to