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, ¶meters_); 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, ¶meters_); 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