scopeinfo.cc revision 85b71799222b55eb5dd74ea26efe0c64ab655c8c
1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h>
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scopeinfo.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scopes.h"
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "allocation-inl.h"
363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic int CompareLocal(Variable* const* v, Variable* const* w) {
4285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int x = (*v)->index();
4385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int y = (*w)->index();
4485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Consider sorting them according to type as well?
4585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return x - y;
4685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
4785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
4885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
4985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate<class Allocator>
5085b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochScopeInfo<Allocator>::ScopeInfo(Scope* scope)
5185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    : function_name_(FACTORY->empty_symbol()),
5285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      calls_eval_(scope->calls_eval()),
5385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      is_strict_mode_(scope->is_strict_mode()),
5485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      parameters_(scope->num_parameters()),
5585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      stack_slots_(scope->num_stack_slots()),
5685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      context_slots_(scope->num_heap_slots()),
5785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      context_modes_(scope->num_heap_slots()) {
58592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Add parameters.
5985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  for (int i = 0; i < scope->num_parameters(); i++) {
6085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ASSERT(parameters_.length() == i);
6185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    parameters_.Add(scope->parameter(i)->name());
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Add stack locals and collect heap locals.
6585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // We are assuming that the locals' slots are allocated in
6685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // increasing order, so we can simply add them to the
6785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // ScopeInfo lists. However, due to usage analysis, this is
6885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // not true for context-allocated locals: Some of them
6985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // may be parameters which are allocated before the
7085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // non-parameter locals. When the non-parameter locals are
7185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // sorted according to usage, the allocated slot indices may
7285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // not be in increasing order with the variable list anymore.
7385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Thus, we first collect the context-allocated locals, and then
7485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // sort them by context slot index before adding them to the
7585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // ScopeInfo list.
7685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  List<Variable*, Allocator> locals(32);  // 32 is a wild guess
7785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(locals.is_empty());
7885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  scope->CollectUsedVariables(&locals);
7985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  locals.Sort(&CompareLocal);
8085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
8185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  List<Variable*, Allocator> heap_locals(locals.length());
8285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  for (int i = 0; i < locals.length(); i++) {
8385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Variable* var = locals[i];
8485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    if (var->is_used()) {
8585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      switch (var->location()) {
8685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        case Variable::UNALLOCATED:
8785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        case Variable::PARAMETER:
8885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          break;
8985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
9085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        case Variable::LOCAL:
9185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          ASSERT(stack_slots_.length() == var->index());
9285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          stack_slots_.Add(var->name());
9385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          break;
9485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
9585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        case Variable::CONTEXT:
9685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          heap_locals.Add(var);
9785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          break;
9885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
9985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        case Variable::LOOKUP:
10085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          // We don't expect lookup variables in the locals list.
10185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          UNREACHABLE();
10285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch          break;
10385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      }
10485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
105592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Add heap locals.
10885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (scope->num_heap_slots() > 0) {
10985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // Add user-defined slots.
11085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    for (int i = 0; i < heap_locals.length(); i++) {
11185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
11285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch             context_slots_.length());
11385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      ASSERT(heap_locals[i]->index() - Context::MIN_CONTEXT_SLOTS ==
11485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch             context_modes_.length());
11585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      context_slots_.Add(heap_locals[i]->name());
11685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      context_modes_.Add(heap_locals[i]->mode());
11785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
11985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  } else {
12085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ASSERT(heap_locals.length() == 0);
121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Add the function context slot, if present.
12485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // For now, this must happen at the very end because of the
12585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // ordering of the scope info slots and the respective slot indices.
12685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (scope->is_function_scope()) {
12785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    VariableProxy* proxy = scope->function();
12885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    if (proxy != NULL &&
12985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        proxy->var()->is_used() &&
13085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        proxy->var()->IsContextSlot()) {
13185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      function_name_ = proxy->name();
13285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      // Note that we must not find the function name in the context slot
13385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      // list - instead it must be handled separately in the
13485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      // Contexts::Lookup() function. Thus record an empty symbol here so we
13585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      // get the correct number of context slots.
13685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
13785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch             context_slots_.length());
13885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
13985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch             context_modes_.length());
14085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      context_slots_.Add(FACTORY->empty_symbol());
14185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      context_modes_.Add(Variable::INTERNAL);
14285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
143592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
14485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
14585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// Encoding format in a FixedArray object:
14885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//
14985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - function name
15085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//
15185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - calls eval boolean flag
15285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//
15385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - number of variables in the context object (smi) (= function context
15485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   slot index + 1)
15585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - list of pairs (name, Var mode) of context-allocated variables (starting
15685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   with context slot 0)
15785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//
15885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - number of parameters (smi)
15985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - list of parameter names (starting with parameter 0 first)
16085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//
16185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - number of variables on the stack (smi)
16285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - list of names of stack-allocated variables (starting with stack slot 0)
16385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
16485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// The ScopeInfo representation could be simplified and the ScopeInfo
16585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// re-implemented (with almost the same interface). Here is a
16685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// suggestion for the new format:
16785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//
16885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - have a single list with all variable names (parameters, stack locals,
16985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   context locals), followed by a list of non-Object* values containing
17085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   the variables information (what kind, index, attributes)
17185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - searching the linear list of names is fast and yields an index into the
17285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   list if the variable name is found
17385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - that list index is then used to find the variable information in the
17485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   subsequent list
17585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - the list entries don't have to be in any particular order, so all the
17685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   current sorting business can go away
17785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - the ScopeInfo lookup routines can be reduced to perhaps a single lookup
17885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   which returns all information at once
17985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// - when gathering the information from a Scope, we only need to iterate
18085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   through the local variables (parameters and context info is already
18185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch//   present)
18285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
18385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
18485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic inline Object** ReadInt(Object** p, int* x) {
18585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  *x = (reinterpret_cast<Smi*>(*p++))->value();
18685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic inline Object** ReadBool(Object** p, bool* x) {
19185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  *x = (reinterpret_cast<Smi*>(*p++))->value() != 0;
19285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic inline Object** ReadSymbol(Object** p, Handle<String>* s) {
19785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  *s = Handle<String>(reinterpret_cast<String*>(*p++));
19885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
19985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
20085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
20185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
20285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate <class Allocator>
20385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
20485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(list->is_empty());
20585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int n;
20685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = ReadInt(p, &n);
20785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  while (n-- > 0) {
20885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Handle<String> s;
20985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadSymbol(p, &s);
21085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    list->Add(s);
21185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
21285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
21385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
21485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
21585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
21685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate <class Allocator>
21785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic Object** ReadList(Object** p,
21885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                         List<Handle<String>, Allocator>* list,
21985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                         List<Variable::Mode, Allocator>* modes) {
22085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(list->is_empty());
22185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int n;
22285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = ReadInt(p, &n);
22385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  while (n-- > 0) {
22485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Handle<String> s;
22585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int m;
22685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadSymbol(p, &s);
22785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadInt(p, &m);
22885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    list->Add(s);
22985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    modes->Add(static_cast<Variable::Mode>(m));
23085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
23185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
23285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
23385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
23485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
23585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate<class Allocator>
23685b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
23785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  : function_name_(FACTORY->empty_symbol()),
23885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    parameters_(4),
23985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    stack_slots_(8),
24085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    context_slots_(8),
24185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    context_modes_(8) {
24285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (data->length() > 0) {
24385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p0 = data->data_start();
24485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = p0;
24585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadSymbol(p, &function_name_);
24685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadBool(p, &calls_eval_);
24785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadBool(p, &is_strict_mode_);
24885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadList<Allocator>(p, &context_slots_, &context_modes_);
24985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadList<Allocator>(p, &parameters_);
25085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadList<Allocator>(p, &stack_slots_);
25185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ASSERT((p - p0) == FixedArray::cast(data)->length());
25285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic inline Object** WriteInt(Object** p, int x) {
25785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  *p++ = Smi::FromInt(x);
25885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic inline Object** WriteBool(Object** p, bool b) {
26385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  *p++ = Smi::FromInt(b ? 1 : 0);
26485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic inline Object** WriteSymbol(Object** p, Handle<String> s) {
26985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  *p++ = *s;
27085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate <class Allocator>
27585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
27685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  const int n = list->length();
27785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteInt(p, n);
27885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  for (int i = 0; i < n; i++) {
27985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = WriteSymbol(p, list->at(i));
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
28185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate <class Allocator>
28685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochstatic Object** WriteList(Object** p,
28785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                          List<Handle<String>, Allocator>* list,
28885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                          List<Variable::Mode, Allocator>* modes) {
28985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  const int n = list->length();
29085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteInt(p, n);
29185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  for (int i = 0; i < n; i++) {
29285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = WriteSymbol(p, list->at(i));
29385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = WriteInt(p, modes->at(i));
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
29585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p;
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate<class Allocator>
30085b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochHandle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
30185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // function name, calls eval, is_strict_mode, length for 3 tables:
30285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  const int extra_slots = 1 + 1 + 1 + 3;
30385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int length = extra_slots +
30485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch               context_slots_.length() * 2 +
30585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch               parameters_.length() +
30685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch               stack_slots_.length();
30785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
30885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Handle<SerializedScopeInfo> data(
30985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      SerializedScopeInfo::cast(*FACTORY->NewSerializedScopeInfo(length)));
31085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  AssertNoAllocation nogc;
31185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
31285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Object** p0 = data->data_start();
31385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Object** p = p0;
31485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteSymbol(p, function_name_);
31585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteBool(p, calls_eval_);
31685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteBool(p, is_strict_mode_);
31785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteList(p, &context_slots_, &context_modes_);
31885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteList(p, &parameters_);
31985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = WriteList(p, &stack_slots_);
32085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT((p - p0) == length);
32185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
32285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return data;
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
32685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate<class Allocator>
32785b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochHandle<String> ScopeInfo<Allocator>::LocalName(int i) const {
32885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // A local variable can be allocated either on the stack or in the context.
32985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // For variables allocated in the context they are always preceded by
33085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Context::MIN_CONTEXT_SLOTS of fixed allocated slots in the context.
33185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (i < number_of_stack_slots()) {
33285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return stack_slot_name(i);
333592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
33485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return context_slot_name(i - number_of_stack_slots() +
33585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                             Context::MIN_CONTEXT_SLOTS);
3363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate<class Allocator>
34185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint ScopeInfo<Allocator>::NumberOfLocals() const {
34285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int number_of_locals = number_of_stack_slots();
34385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (number_of_context_slots() > 0) {
34485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
34585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
34785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return number_of_locals;
3483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
3493bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
3503bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
35185b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochHandle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) {
35285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
35385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return sinfo.Serialize();
3543bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
3553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
3563bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
35785b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochSerializedScopeInfo* SerializedScopeInfo::Empty() {
35885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return reinterpret_cast<SerializedScopeInfo*>(HEAP->empty_fixed_array());
3593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
3603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
3613bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
36285b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochObject** SerializedScopeInfo::ContextEntriesAddr() {
36385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(length() > 0);
36485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // +3 for function name, calls eval, strict mode.
36585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return data_start() + 3;
366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
36985b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochObject** SerializedScopeInfo::ParameterEntriesAddr() {
37085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(length() > 0);
37185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Object** p = ContextEntriesAddr();
37285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int number_of_context_slots;
37385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = ReadInt(p, &number_of_context_slots);
37485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p + number_of_context_slots*2;  // *2 for pairs
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37885b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochObject** SerializedScopeInfo::StackSlotEntriesAddr() {
37985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(length() > 0);
38085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Object** p = ParameterEntriesAddr();
38185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int number_of_parameter_slots;
38285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  p = ReadInt(p, &number_of_parameter_slots);
38385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return p + number_of_parameter_slots;
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
38785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochbool SerializedScopeInfo::CallsEval() {
38885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (length() > 0) {
38985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = data_start() + 1;  // +1 for function name.
39085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    bool calls_eval;
39185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadBool(p, &calls_eval);
39285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return calls_eval;
39385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
39485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return false;
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochbool SerializedScopeInfo::IsStrictMode() {
39985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (length() > 0) {
40085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = data_start() + 2;  // +2 for function name, calls eval.
40185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    bool strict_mode;
40285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = ReadBool(p, &strict_mode);
40385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return strict_mode;
40485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
40585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return false;
4069dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
4079dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
4089dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
40985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint SerializedScopeInfo::NumberOfStackSlots() {
4103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
41185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = StackSlotEntriesAddr();
41285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int number_of_stack_slots;
41385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ReadInt(p, &number_of_stack_slots);
41485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return number_of_stack_slots;
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
41685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return 0;
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
419592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
42085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint SerializedScopeInfo::NumberOfContextSlots() {
42185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (length() > 0) {
42285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = ContextEntriesAddr();
42385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int number_of_context_slots;
42485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ReadInt(p, &number_of_context_slots);
42585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return number_of_context_slots + Context::MIN_CONTEXT_SLOTS;
42685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
42785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return 0;
42885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
42985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
43085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
43185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochbool SerializedScopeInfo::HasHeapAllocatedLocals() {
43285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (length() > 0) {
43385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = ContextEntriesAddr();
43485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int number_of_context_slots;
43585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ReadInt(p, &number_of_context_slots);
43685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    return number_of_context_slots > 0;
43785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
43885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return false;
43985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
44085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
44185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
44285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint SerializedScopeInfo::StackSlotIndex(String* name) {
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(name->IsSymbol());
4443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
44585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // Slots start after length entry.
44685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p0 = StackSlotEntriesAddr();
44785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int number_of_stack_slots;
44885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p0 = ReadInt(p0, &number_of_stack_slots);
44985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = p0;
45085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** end = p0 + number_of_stack_slots;
45185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    while (p != end) {
45285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      if (*p == name) return static_cast<int>(p - p0);
45385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      p++;
454592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
45585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
45685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return -1;
45785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
458592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
45985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
46085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  ASSERT(name->IsSymbol());
46185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  Isolate* isolate = GetIsolate();
46285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  int result = isolate->context_slot_cache()->Lookup(this, name, mode);
46385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (result != ContextSlotCache::kNotFound) return result;
46485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (length() > 0) {
46585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // Slots start after length entry.
46685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p0 = ContextEntriesAddr();
46785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int number_of_context_slots;
46885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p0 = ReadInt(p0, &number_of_context_slots);
46985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = p0;
47085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** end = p0 + number_of_context_slots * 2;
47185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    while (p != end) {
47285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      if (*p == name) {
47385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        ASSERT(((p - p0) & 1) == 0);
47485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        int v;
47585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        ReadInt(p + 1, &v);
47685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        Variable::Mode mode_value = static_cast<Variable::Mode>(v);
47785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        if (mode != NULL) *mode = mode_value;
47885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
47985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch        isolate->context_slot_cache()->Update(this, name, mode_value, result);
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return result;
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
48285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      p += 2;
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
48585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  isolate->context_slot_cache()->Update(this, name, Variable::INTERNAL, -1);
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint SerializedScopeInfo::ParameterIndex(String* name) {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(name->IsSymbol());
4923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We must read parameters from the end since for
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // multiply declared parameters the value of the
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // last declaration of that parameter is used
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // inside a function (and thus we need to look
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // at the last index). Was bug# 1110337.
49885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    //
49985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // Eventually, we should only register such parameters
50085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // once, with corresponding index. This requires a new
50185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // implementation of the ScopeInfo code. See also other
50285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    // comments in this file regarding this.
50385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = ParameterEntriesAddr();
50485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    int number_of_parameter_slots;
50585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p0 = ReadInt(p, &number_of_parameter_slots);
50685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    p = p0 + number_of_parameter_slots;
50785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    while (p > p0) {
50885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      p--;
50985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      if (*p == name) return static_cast<int>(p - p0);
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
51685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint SerializedScopeInfo::FunctionContextSlotIndex(String* name) {
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(name->IsSymbol());
5183bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
51985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    Object** p = data_start();
52085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    if (*p == name) {
52185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      p = ContextEntriesAddr();
52285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      int number_of_context_slots;
52385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      ReadInt(p, &number_of_context_slots);
52485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      ASSERT(number_of_context_slots != 0);
52585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      // The function context slot is the last entry.
52685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochint ContextSlotCache::Hash(Object* data, String* name) {
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Uses only lower 32 bits if pointers are larger.
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uintptr_t addr_hash =
5363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
537402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochint ContextSlotCache::Lookup(Object* data,
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                             String* name,
54385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                             Variable::Mode* mode) {
5443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  int index = Hash(data, name);
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Key& key = keys_[index];
5463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if ((key.data == data) && key.name->Equals(name)) {
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Value result(values_[index]);
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mode != NULL) *mode = result.mode();
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return result.index() + kNotFound;
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return kNotFound;
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid ContextSlotCache::Update(Object* data,
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              String* name,
55785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                              Variable::Mode mode,
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              int slot_index) {
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String* symbol;
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(slot_index > kNotFound);
56144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HEAP->LookupSymbolIfExists(name, &symbol)) {
5623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    int index = Hash(data, symbol);
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Key& key = keys_[index];
5643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    key.data = data;
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    key.name = symbol;
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Please note value only takes a uint as index.
56785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    values_[index] = Value(mode, slot_index - kNotFound).raw();
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
56985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    ValidateEntry(data, name, mode, slot_index);
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ContextSlotCache::Clear() {
5763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5823bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid ContextSlotCache::ValidateEntry(Object* data,
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     String* name,
58485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                                     Variable::Mode mode,
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int slot_index) {
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  String* symbol;
58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (HEAP->LookupSymbolIfExists(name, &symbol)) {
5883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    int index = Hash(data, name);
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Key& key = keys_[index];
5903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch    ASSERT(key.data == data);
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(key.name->Equals(name));
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Value result(values_[index]);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(result.mode() == mode);
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(result.index() + kNotFound == slot_index);
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate <class Allocator>
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PrintList(const char* list_name,
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      int nof_internal_slots,
60285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                      List<Handle<String>, Allocator>& list) {
60385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (list.length() > 0) {
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("\n  // %s\n", list_name);
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (nof_internal_slots > 0) {
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
60885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    for (int i = 0; i < list.length(); i++) {
60985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      PrintF("  %2d ", i + nof_internal_slots);
61085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch      list[i]->ShortPrint();
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("\n");
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
61785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate<class Allocator>
61885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochvoid ScopeInfo<Allocator>::Print() {
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("ScopeInfo ");
62085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  if (function_name_->length() > 0)
62185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    function_name_->ShortPrint();
62285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  else
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("/* no function name */");
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("{");
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
62685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  PrintList<Allocator>("parameters", 0, parameters_);
62785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  PrintList<Allocator>("stack slots", 0, stack_slots_);
62885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  PrintList<Allocator>("context slots", Context::MIN_CONTEXT_SLOTS,
62985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                       context_slots_);
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("}\n");
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // DEBUG
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
63685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch// Make sure the classes get instantiated by the template system.
63785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate class ScopeInfo<FreeStoreAllocationPolicy>;
63885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate class ScopeInfo<PreallocatedStorage>;
63985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochtemplate class ScopeInfo<ZoneListAllocationPolicy>;
64085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
642