1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h>
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopeinfo.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h"
113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<ScopeInfo> ScopeInfo::Create(Scope* scope, Zone* zone) {
173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Collect stack and context locals.
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Variable*> stack_locals(scope->StackLocalCount(), zone);
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneList<Variable*> context_locals(scope->ContextLocalCount(), zone);
203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope->CollectStackAndContextLocals(&stack_locals, &context_locals);
213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int stack_local_count = stack_locals.length();
223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int context_local_count = context_locals.length();
233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Make sure we allocate the correct amount.
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope->StackLocalCount() == stack_local_count);
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope->ContextLocalCount() == context_local_count);
263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Determine use and location of the function variable if it is present.
283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FunctionVariableInfo function_name_info;
293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  VariableMode function_variable_mode;
303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (scope->is_function_scope() && scope->function() != NULL) {
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var = scope->function()->proxy()->var();
323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!var->is_used()) {
333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function_name_info = UNUSED;
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (var->IsContextSlot()) {
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function_name_info = CONTEXT;
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(var->IsStackLocal());
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      function_name_info = STACK;
3985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    }
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    function_variable_mode = var->mode();
4185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  } else {
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    function_name_info = NONE;
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    function_variable_mode = VAR;
44592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const bool has_function_name = function_name_info != NONE;
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int parameter_count = scope->num_parameters();
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const int length = kVariablePartIndex
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      + parameter_count + stack_local_count + 2 * context_local_count
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      + (has_function_name ? 2 : 0);
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Factory* factory = zone->isolate()->factory();
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<ScopeInfo> scope_info = factory->NewScopeInfo(length);
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Encode the flags.
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int flags = ScopeTypeField::encode(scope->scope_type()) |
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              CallsEvalField::encode(scope->calls_eval()) |
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              StrictModeField::encode(scope->strict_mode()) |
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FunctionVariableField::encode(function_name_info) |
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              FunctionVariableMode::encode(function_variable_mode) |
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AsmModuleField::encode(scope->asm_module()) |
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              AsmFunctionField::encode(scope->asm_function());
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope_info->SetFlags(flags);
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope_info->SetParameterCount(parameter_count);
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope_info->SetStackLocalCount(stack_local_count);
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  scope_info->SetContextLocalCount(context_local_count);
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int index = kVariablePartIndex;
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add parameters.
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index == scope_info->ParameterEntriesIndex());
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < parameter_count; ++i) {
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope_info->set(index++, *scope->parameter(i)->name());
73592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add stack locals' names. We are assuming that the stack locals'
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // slots are allocated in increasing order, so we can simply add
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // them to the ScopeInfo object.
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index == scope_info->StackLocalEntriesIndex());
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < stack_local_count; ++i) {
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(stack_locals[i]->index() == i);
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope_info->set(index++, *stack_locals[i]->name());
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Due to usage analysis, context-allocated locals are not necessarily in
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // increasing order: Some of them may be parameters which are allocated before
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the non-parameter locals. When the non-parameter locals are sorted
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // according to usage, the allocated slot indices may not be in increasing
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // order with the variable list anymore. Thus, we first need to sort them by
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // context slot index before adding them to the ScopeInfo object.
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  context_locals.Sort(&Variable::CompareIndex);
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add context locals' names.
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index == scope_info->ContextLocalNameEntriesIndex());
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < context_local_count; ++i) {
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope_info->set(index++, *context_locals[i]->name());
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
9785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Add context locals' info.
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < context_local_count; ++i) {
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Variable* var = context_locals[i];
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t value =
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ContextLocalMode::encode(var->mode()) |
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ContextLocalInitFlag::encode(var->initialization_flag()) |
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope_info->set(index++, Smi::FromInt(value));
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If present, add the function variable name and its index.
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index == scope_info->FunctionNameEntryIndex());
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (has_function_name) {
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int var_index = scope->function()->proxy()->var()->index();
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    scope_info->set(index++, *scope->function()->proxy()->name());
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope_info->set(index++, Smi::FromInt(var_index));
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(function_name_info != STACK ||
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           (var_index == scope_info->StackLocalCount() &&
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            var_index == scope_info->StackSlotCount() - 1));
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(function_name_info != CONTEXT ||
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           var_index == scope_info->ContextLength() - 1);
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(index == scope_info->length());
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope->num_parameters() == scope_info->ParameterCount());
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope->num_stack_slots() == scope_info->StackSlotCount());
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(scope->num_heap_slots() == scope_info->ContextLength() ||
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         (scope->num_heap_slots() == kVariablePartIndex &&
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          scope_info->ContextLength() == 0));
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return scope_info;
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochScopeInfo* ScopeInfo::Empty(Isolate* isolate) {
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return reinterpret_cast<ScopeInfo*>(isolate->heap()->empty_fixed_array());
13485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
13585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
13685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochScopeType ScopeInfo::scope_type() {
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length() > 0);
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ScopeTypeField::decode(Flags());
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool ScopeInfo::CallsEval() {
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return length() > 0 && CallsEvalField::decode(Flags());
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochStrictMode ScopeInfo::strict_mode() {
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return length() > 0 ? StrictModeField::decode(Flags()) : SLOPPY;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::LocalCount() {
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return StackLocalCount() + ContextLocalCount();
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::StackSlotCount() {
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (length() > 0) {
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool function_name_stack_slot =
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FunctionVariableField::decode(Flags()) == STACK;
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return StackLocalCount() + (function_name_stack_slot ? 1 : 0);
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return 0;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::ContextLength() {
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (length() > 0) {
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int context_locals = ContextLocalCount();
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool function_name_context_slot =
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FunctionVariableField::decode(Flags()) == CONTEXT;
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool has_context = context_locals > 0 ||
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        function_name_context_slot ||
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scope_type() == WITH_SCOPE ||
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        (scope_type() == FUNCTION_SCOPE && CallsEval()) ||
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scope_type() == MODULE_SCOPE;
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (has_context) {
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Context::MIN_CONTEXT_SLOTS + context_locals +
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          (function_name_context_slot ? 1 : 0);
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return 0;
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool ScopeInfo::HasFunctionName() {
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (length() > 0) {
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return NONE != FunctionVariableField::decode(Flags());
190592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } else {
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return false;
1923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  }
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool ScopeInfo::HasHeapAllocatedLocals() {
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (length() > 0) {
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ContextLocalCount() > 0;
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return false;
201592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
2023bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch}
2033bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2043bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool ScopeInfo::HasContext() {
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ContextLength() > 0;
207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochString* ScopeInfo::FunctionName() {
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(HasFunctionName());
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return String::cast(get(FunctionNameEntryIndex()));
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochString* ScopeInfo::ParameterName(int var) {
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < ParameterCount());
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int info_index = ParameterEntriesIndex() + var;
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return String::cast(get(info_index));
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochString* ScopeInfo::LocalName(int var) {
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < LocalCount());
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(StackLocalEntriesIndex() + StackLocalCount() ==
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         ContextLocalNameEntriesIndex());
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int info_index = StackLocalEntriesIndex() + var;
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return String::cast(get(info_index));
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochString* ScopeInfo::StackLocalName(int var) {
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < StackLocalCount());
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int info_index = StackLocalEntriesIndex() + var;
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return String::cast(get(info_index));
2369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen}
2379dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2389dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochString* ScopeInfo::ContextLocalName(int var) {
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < ContextLocalCount());
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int info_index = ContextLocalNameEntriesIndex() + var;
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return String::cast(get(info_index));
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
245592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVariableMode ScopeInfo::ContextLocalMode(int var) {
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < ContextLocalCount());
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int info_index = ContextLocalInfoEntriesIndex() + var;
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int value = Smi::cast(get(info_index))->value();
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ContextLocalMode::decode(value);
25185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
25285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
25385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochInitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < ContextLocalCount());
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int info_index = ContextLocalInfoEntriesIndex() + var;
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int value = Smi::cast(get(info_index))->value();
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ContextLocalInitFlag::decode(value);
25985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
26085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
26185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochMaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) {
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < ContextLocalCount());
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int info_index = ContextLocalInfoEntriesIndex() + var;
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int value = Smi::cast(get(info_index))->value();
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return ContextLocalMaybeAssignedFlag::decode(value);
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool ScopeInfo::LocalIsSynthetic(int var) {
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(0 <= var && var < LocalCount());
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // There's currently no flag stored on the ScopeInfo to indicate that a
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // variable is a compiler-introduced temporary. However, to avoid conflict
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with user declarations, the current temporaries like .generator_object and
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // .result start with a dot, so we can use that as a flag. It's a hack!
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> name(LocalName(var));
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return name->length() > 0 && name->Get(0) == '.';
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::StackSlotIndex(String* name) {
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(name->IsInternalizedString());
2833bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int start = StackLocalEntriesIndex();
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int end = StackLocalEntriesIndex() + StackLocalCount();
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = start; i < end; ++i) {
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (name == get(i)) {
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return i - start;
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
290592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
29185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  }
29285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  return -1;
29385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch}
294592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                Handle<String> name, VariableMode* mode,
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                InitializationFlag* init_flag,
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                MaybeAssignedFlag* maybe_assigned_flag) {
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(name->IsInternalizedString());
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(mode != NULL);
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(init_flag != NULL);
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (scope_info->length() > 0) {
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ContextSlotCache* context_slot_cache =
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scope_info->GetIsolate()->context_slot_cache();
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int result = context_slot_cache->Lookup(*scope_info, *name, mode, init_flag,
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            maybe_assigned_flag);
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (result != ContextSlotCache::kNotFound) {
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(result < scope_info->ContextLength());
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return result;
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int start = scope_info->ContextLocalNameEntriesIndex();
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int end = scope_info->ContextLocalNameEntriesIndex() +
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        scope_info->ContextLocalCount();
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = start; i < end; ++i) {
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (*name == scope_info->get(i)) {
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int var = i - start;
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *mode = scope_info->ContextLocalMode(var);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *init_flag = scope_info->ContextLocalInitFlag(var);
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        *maybe_assigned_flag = scope_info->ContextLocalMaybeAssignedFlag(var);
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        result = Context::MIN_CONTEXT_SLOTS + var;
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        context_slot_cache->Update(scope_info, name, *mode, *init_flag,
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                   *maybe_assigned_flag, result);
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DCHECK(result < scope_info->ContextLength());
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        return result;
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Cache as not found. Mode, init flag and maybe assigned flag don't matter.
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    context_slot_cache->Update(scope_info, name, INTERNAL, kNeedsInitialization,
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               kNotAssigned, -1);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::ParameterIndex(String* name) {
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(name->IsInternalizedString());
3393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // We must read parameters from the end since for
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // multiply declared parameters the value of the
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // last declaration of that parameter is used
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // inside a function (and thus we need to look
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // at the last index). Was bug# 1110337.
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int start = ParameterEntriesIndex();
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int end = ParameterEntriesIndex() + ParameterCount();
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = end - 1; i >= start; --i) {
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (name == get(i)) {
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return i - start;
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::FunctionContextSlotIndex(String* name, VariableMode* mode) {
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(name->IsInternalizedString());
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(mode != NULL);
3603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if (length() > 0) {
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FunctionVariableField::decode(Flags()) == CONTEXT &&
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        FunctionName() == name) {
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *mode = FunctionVariableMode::decode(Flags());
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Smi::cast(get(FunctionNameEntryIndex() + 1))->value();
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return -1;
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool ScopeInfo::CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Handle<Context> context,
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                               Handle<JSObject> scope_object) {
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = scope_info->GetIsolate();
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int local_count = scope_info->ContextLocalCount();
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (local_count == 0) return true;
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fill all context locals to the context extension.
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int first_context_var = scope_info->StackLocalCount();
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int start = scope_info->ContextLocalNameEntriesIndex();
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < local_count; ++i) {
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (scope_info->LocalIsSynthetic(first_context_var + i)) continue;
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int context_index = Context::MIN_CONTEXT_SLOTS + i;
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RETURN_ON_EXCEPTION_VALUE(
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate,
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Runtime::DefineObjectProperty(
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            scope_object,
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Handle<String>(String::cast(scope_info->get(i + start))),
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            Handle<Object>(context->get(context_index), isolate),
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            ::NONE),
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        false);
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return true;
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::ParameterEntriesIndex() {
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(length() > 0);
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return kVariablePartIndex;
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::StackLocalEntriesIndex() {
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ParameterEntriesIndex() + ParameterCount();
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::ContextLocalNameEntriesIndex() {
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return StackLocalEntriesIndex() + StackLocalCount();
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::ContextLocalInfoEntriesIndex() {
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ContextLocalNameEntriesIndex() + ContextLocalCount();
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ScopeInfo::FunctionNameEntryIndex() {
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return ContextLocalInfoEntriesIndex() + ContextLocalCount();
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochint ContextSlotCache::Hash(Object* data, String* name) {
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Uses only lower 32 bits if pointers are larger.
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uintptr_t addr_hash =
4253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(data)) >> 2;
426402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint ContextSlotCache::Lookup(Object* data, String* name, VariableMode* mode,
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             InitializationFlag* init_flag,
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             MaybeAssignedFlag* maybe_assigned_flag) {
4333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  int index = Hash(data, name);
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Key& key = keys_[index];
4353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  if ((key.data == data) && key.name->Equals(name)) {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Value result(values_[index]);
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (mode != NULL) *mode = result.mode();
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (init_flag != NULL) *init_flag = result.initialization_flag();
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (maybe_assigned_flag != NULL)
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *maybe_assigned_flag = result.maybe_assigned_flag();
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return result.index() + kNotFound;
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return kNotFound;
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ContextSlotCache::Update(Handle<Object> data, Handle<String> name,
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              VariableMode mode, InitializationFlag init_flag,
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              MaybeAssignedFlag maybe_assigned_flag,
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              int slot_index) {
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> internalized_name;
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(slot_index > kNotFound);
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ToHandle(&internalized_name)) {
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int index = Hash(*data, *internalized_name);
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Key& key = keys_[index];
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    key.data = *data;
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    key.name = *internalized_name;
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Please note value only takes a uint as index.
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    values_[index] = Value(mode, init_flag, maybe_assigned_flag,
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           slot_index - kNotFound).raw();
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ValidateEntry(data, name, mode, init_flag, maybe_assigned_flag, slot_index);
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ContextSlotCache::Clear() {
4713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  for (int index = 0; index < kLength; index++) keys_[index].data = NULL;
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ContextSlotCache::ValidateEntry(Handle<Object> data, Handle<String> name,
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     VariableMode mode,
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     InitializationFlag init_flag,
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                     MaybeAssignedFlag maybe_assigned_flag,
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                     int slot_index) {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DisallowHeapAllocation no_gc;
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<String> internalized_name;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (StringTable::InternalizeStringIfExists(name->GetIsolate(), name).
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ToHandle(&internalized_name)) {
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int index = Hash(*data, *name);
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Key& key = keys_[index];
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(key.data == *data);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(key.name->Equals(*name));
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Value result(values_[index]);
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result.mode() == mode);
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result.initialization_flag() == init_flag);
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result.maybe_assigned_flag() == maybe_assigned_flag);
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(result.index() + kNotFound == slot_index);
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void PrintList(const char* list_name,
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                      int nof_internal_slots,
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      int start,
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      int end,
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      ScopeInfo* scope_info) {
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (start < end) {
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("\n  // %s\n", list_name);
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (nof_internal_slots > 0) {
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("  %2d - %2d [internal slots]\n", 0 , nof_internal_slots - 1);
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int i = nof_internal_slots; start < end; ++i, ++start) {
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("  %2d ", i);
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      String::cast(scope_info->get(start))->ShortPrint();
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      PrintF("\n");
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid ScopeInfo::Print() {
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("ScopeInfo ");
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (HasFunctionName()) {
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FunctionName()->ShortPrint();
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PrintF("/* no function name */");
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("{");
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrintList("parameters", 0,
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ParameterEntriesIndex(),
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ParameterEntriesIndex() + ParameterCount(),
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            this);
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrintList("stack slots", 0,
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            StackLocalEntriesIndex(),
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            StackLocalEntriesIndex() + StackLocalCount(),
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            this);
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PrintList("context slots",
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Context::MIN_CONTEXT_SLOTS,
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ContextLocalNameEntriesIndex(),
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ContextLocalNameEntriesIndex() + ContextLocalCount(),
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            this);
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintF("}\n");
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // DEBUG
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//---------------------------------------------------------------------------
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ModuleInfo.
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochHandle<ModuleInfo> ModuleInfo::Create(
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Isolate* isolate, Interface* interface, Scope* scope) {
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<ModuleInfo> info = Allocate(isolate, interface->Length());
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  info->set_host_index(interface->Index());
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int i = 0;
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (Interface::Iterator it = interface->iterator();
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch       !it.done(); it.Advance(), ++i) {
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Variable* var = scope->LookupLocal(it.name());
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info->set_name(i, *(it.name()->string()));
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    info->set_mode(i, var->mode());
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((var->mode() == MODULE) == (it.interface()->IsModule()));
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (var->mode() == MODULE) {
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(it.interface()->IsFrozen());
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(it.interface()->Index() >= 0);
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->set_index(i, it.interface()->Index());
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(var->index() >= 0);
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->set_index(i, var->index());
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(i == info->length());
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return info;
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
574