// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
int ignored = 0;
- EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored);
+ EmitDeclaration(scope()->function(), CONST, NULL, &ignored);
}
VisitDeclarations(scope()->declarations());
}
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* function,
int* global_count) {
// If it was not possible to allocate the variable at compile time, we
Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
__ str(result_register(), StackOperand(variable));
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ str(ip, StackOperand(variable));
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ str(ip, ContextOperand(cp, variable->index()));
Comment cmnt(masm_, "[ Declaration");
__ mov(r2, Operand(variable->name()));
// Declaration nodes are always introduced in one of three modes.
- ASSERT(mode == Variable::VAR ||
- mode == Variable::CONST ||
- mode == Variable::LET);
- PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
+ ASSERT(mode == VAR || mode == CONST || mode == LET);
+ PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE;
__ mov(r1, Operand(Smi::FromInt(attr)));
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
__ Push(cp, r2, r1);
// Push initial value for function declaration.
VisitForStackValue(function);
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
__ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
__ Push(cp, r2, r1, r0);
} else {
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
- if (var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (var->mode() == DYNAMIC_GLOBAL) {
EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
__ jmp(done);
- } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
+ } else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == Variable::CONST ||
- local->mode() == Variable::LET) {
+ if (local->mode() == CONST ||
+ local->mode() == LET) {
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
- if (local->mode() == Variable::CONST) {
+ if (local->mode() == CONST) {
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
- } else { // Variable::LET
+ } else { // LET
__ b(ne, done);
__ mov(r0, Operand(var->name()));
__ push(r0);
Comment cmnt(masm_, var->IsContextSlot()
? "Context variable"
: "Stack variable");
- if (var->mode() != Variable::LET && var->mode() != Variable::CONST) {
+ if (var->mode() != LET && var->mode() != CONST) {
context()->Plug(var);
} else {
// Let and const need a read barrier.
GetVar(r0, var);
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
- if (var->mode() == Variable::LET) {
+ if (var->mode() == LET) {
Label done;
__ b(ne, &done);
__ mov(r0, Operand(var->name()));
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
- } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ } else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
__ push(r0); // Value.
}
}
- } else if (var->mode() != Variable::CONST) {
+ } else if (var->mode() != CONST) {
// Assignment to var or initializing assignment to let.
if (var->IsStackAllocated() || var->IsContextSlot()) {
MemOperand location = VarOperand(var, r1);
// context lookup in the runtime system.
Label done;
Variable* var = proxy->var();
- if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (!var->IsUnallocated() && var->mode() == DYNAMIC_GLOBAL) {
Label slow;
EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
// Push the function and resolve eval.
class Declaration: public AstNode {
public:
Declaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* fun,
Scope* scope)
: proxy_(proxy),
mode_(mode),
fun_(fun),
scope_(scope) {
- ASSERT(mode == Variable::VAR ||
- mode == Variable::CONST ||
- mode == Variable::LET);
+ ASSERT(mode == VAR || mode == CONST || mode == LET);
// At the moment there are no "const functions"'s in JavaScript...
- ASSERT(fun == NULL || mode == Variable::VAR || mode == Variable::LET);
+ ASSERT(fun == NULL || mode == VAR || mode == LET);
}
DECLARE_NODE_TYPE(Declaration)
VariableProxy* proxy() const { return proxy_; }
- Variable::Mode mode() const { return mode_; }
+ VariableMode mode() const { return mode_; }
FunctionLiteral* fun() const { return fun_; } // may be NULL
virtual bool IsInlineable() const;
Scope* scope() const { return scope_; }
private:
VariableProxy* proxy_;
- Variable::Mode mode_;
+ VariableMode mode_;
FunctionLiteral* fun_;
// Nested scope from which the declaration originated.
scope_info = Handle<SerializedScopeInfo>(
SerializedScopeInfo::cast(context->extension()), isolate);
}
- Variable::Mode mode;
+ VariableMode mode;
int slot_index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
if (slot_index >= 0) {
// declared variables that were introduced through declaration nodes)
// must not appear here.
switch (mode) {
- case Variable::INTERNAL: // Fall through.
- case Variable::VAR:
+ case INTERNAL: // Fall through.
+ case VAR:
*attributes = NONE;
*binding_flags = MUTABLE_IS_INITIALIZED;
break;
- case Variable::LET:
+ case LET:
*attributes = NONE;
*binding_flags = MUTABLE_CHECK_INITIALIZED;
break;
- case Variable::CONST:
+ case CONST:
*attributes = READ_ONLY;
*binding_flags = IMMUTABLE_CHECK_INITIALIZED;
break;
- case Variable::DYNAMIC:
- case Variable::DYNAMIC_GLOBAL:
- case Variable::DYNAMIC_LOCAL:
- case Variable::TEMPORARY:
+ case DYNAMIC:
+ case DYNAMIC_GLOBAL:
+ case DYNAMIC_LOCAL:
+ case TEMPORARY:
UNREACHABLE();
break;
}
// Check non-parameter locals.
Handle<SerializedScopeInfo> scope_info(
context->closure()->shared()->scope_info());
- Variable::Mode mode;
+ VariableMode mode;
int index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (index >= 0) return false;
if (var->IsUnallocated()) {
array->set(j++, *(var->name()));
if (decl->fun() == NULL) {
- if (var->mode() == Variable::CONST) {
+ if (var->mode() == CONST) {
// In case this is const property use the hole.
array->set_the_hole(j++);
} else {
// Platform-specific code for a variable, constant, or function
// declaration. Functions have an initial value.
void EmitDeclaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* function,
int* global_count);
// Handle implicit declaration of the function name in named function
// expressions before other declarations.
if (scope->is_function_scope() && scope->function() != NULL) {
- HandleDeclaration(scope->function(), Variable::CONST, NULL);
+ HandleDeclaration(scope->function(), CONST, NULL);
}
VisitDeclarations(scope->declarations());
AddSimulate(AstNode::kDeclarationsId);
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
Variable* variable = expr->var();
- if (variable->mode() == Variable::LET) {
+ if (variable->mode() == LET) {
return Bailout("reference to let variable");
}
switch (variable->location()) {
case Variable::PARAMETER:
case Variable::LOCAL: {
HValue* value = environment()->Lookup(variable);
- if (variable->mode() == Variable::CONST &&
+ if (variable->mode() == CONST &&
value == graph()->GetConstantHole()) {
return Bailout("reference to uninitialized const variable");
}
}
case Variable::CONTEXT: {
- if (variable->mode() == Variable::CONST) {
+ if (variable->mode() == CONST) {
return Bailout("reference to const context slot");
}
HValue* context = BuildContextChainWalk(variable);
if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == Variable::CONST || var->mode() == Variable::LET) {
+ if (var->mode() == CONST || var->mode() == LET) {
return Bailout("unsupported let or const compound assignment");
}
HandlePropertyAssignment(expr);
} else if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == Variable::CONST) {
+ if (var->mode() == CONST) {
if (expr->op() != Token::INIT_CONST) {
return Bailout("non-initializer assignment to const");
}
// variables (e.g. initialization inside a loop).
HValue* old_value = environment()->Lookup(var);
AddInstruction(new HUseConst(old_value));
- } else if (var->mode() == Variable::LET) {
+ } else if (var->mode() == LET) {
return Bailout("unsupported assignment to let");
}
}
case Variable::CONTEXT: {
- ASSERT(var->mode() != Variable::CONST);
+ ASSERT(var->mode() != CONST);
// Bail out if we try to mutate a parameter value in a function using
// the arguments object. We do not (yet) correctly handle the
// arguments property of the function.
if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == Variable::CONST) {
+ if (var->mode() == CONST) {
return Bailout("unsupported count operation with const");
}
// Argument of the count operation is a variable, not a property.
void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* function) {
- if (mode == Variable::LET) return Bailout("unsupported let declaration");
+ if (mode == LET) return Bailout("unsupported let declaration");
Variable* var = proxy->var();
switch (var->location()) {
case Variable::UNALLOCATED:
case Variable::PARAMETER:
case Variable::LOCAL:
case Variable::CONTEXT:
- if (mode == Variable::CONST || function != NULL) {
+ if (mode == CONST || function != NULL) {
HValue* value = NULL;
- if (mode == Variable::CONST) {
+ if (mode == CONST) {
value = graph()->GetConstantHole();
} else {
VisitForValue(function);
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
void HandleDeclaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* function);
void VisitDelete(UnaryOperation* expr);
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
int ignored = 0;
- EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored);
+ EmitDeclaration(scope()->function(), CONST, NULL, &ignored);
}
VisitDeclarations(scope()->declarations());
}
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* function,
int* global_count) {
// If it was not possible to allocate the variable at compile time, we
Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
__ mov(StackOperand(variable), result_register());
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
Comment cmnt(masm_, "[ Declaration");
__ mov(StackOperand(variable),
Immediate(isolate()->factory()->the_hole_value()));
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
Comment cmnt(masm_, "[ Declaration");
__ mov(ContextOperand(esi, variable->index()),
Immediate(isolate()->factory()->the_hole_value()));
__ push(esi);
__ push(Immediate(variable->name()));
// Declaration nodes are always introduced in one of three modes.
- ASSERT(mode == Variable::VAR ||
- mode == Variable::CONST ||
- mode == Variable::LET);
- PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
+ ASSERT(mode == VAR || mode == CONST || mode == LET);
+ PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE;
__ push(Immediate(Smi::FromInt(attr)));
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
increment_stack_height(3);
if (function != NULL) {
VisitForStackValue(function);
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
__ push(Immediate(isolate()->factory()->the_hole_value()));
increment_stack_height();
} else {
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
- if (var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (var->mode() == DYNAMIC_GLOBAL) {
EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
__ jmp(done);
- } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
+ } else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == Variable::CONST ||
- local->mode() == Variable::LET) {
+ if (local->mode() == CONST ||
+ local->mode() == LET) {
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, done);
- if (local->mode() == Variable::CONST) {
+ if (local->mode() == CONST) {
__ mov(eax, isolate()->factory()->undefined_value());
- } else { // Variable::LET
+ } else { // LET
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError, 1);
}
Comment cmnt(masm_, var->IsContextSlot()
? "Context variable"
: "Stack variable");
- if (var->mode() != Variable::LET && var->mode() != Variable::CONST) {
+ if (var->mode() != LET && var->mode() != CONST) {
context()->Plug(var);
} else {
// Let and const need a read barrier.
GetVar(eax, var);
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, &done, Label::kNear);
- if (var->mode() == Variable::LET) {
+ if (var->mode() == LET) {
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError, 1);
- } else { // Variable::CONST
+ } else { // CONST
__ mov(eax, isolate()->factory()->undefined_value());
}
__ bind(&done);
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
- } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ } else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
__ push(eax); // Value.
}
}
- } else if (var->mode() != Variable::CONST) {
+ } else if (var->mode() != CONST) {
// Assignment to var or initializing assignment to let.
if (var->IsStackAllocated() || var->IsContextSlot()) {
MemOperand location = VarOperand(var, ecx);
// context lookup in the runtime system.
Label done;
Variable* var = proxy->var();
- if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (!var->IsUnallocated() && var->mode() == DYNAMIC_GLOBAL) {
Label slow;
EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
// Push the function and resolve eval.
// Multiple break points.
return FixedArray::cast(break_point_objects())->length();
}
-#endif
+#endif // ENABLE_DEBUGGER_SUPPORT
} } // namespace v8::internal
};
+// This object provides quick access to scope info details for runtime
+// routines w/o the need to explicitly create a ScopeInfo object.
+class SerializedScopeInfo : public FixedArray {
+ public :
+ static SerializedScopeInfo* cast(Object* object) {
+ ASSERT(object->IsSerializedScopeInfo());
+ return reinterpret_cast<SerializedScopeInfo*>(object);
+ }
+
+ // Does this scope call eval?
+ bool CallsEval();
+
+ // Is this scope a strict mode scope?
+ bool IsStrictMode();
+
+ // Return the number of stack slots for code.
+ int NumberOfStackSlots();
+
+ // Return the number of context slots for code.
+ int NumberOfContextSlots();
+
+ // Return if this has context slots besides MIN_CONTEXT_SLOTS;
+ bool HasHeapAllocatedLocals();
+
+ // Lookup support for serialized scope info. Returns the
+ // the stack slot index for a given slot name if the slot is
+ // present; otherwise returns a value < 0. The name must be a symbol
+ // (canonicalized).
+ int StackSlotIndex(String* name);
+
+ // Lookup support for serialized scope info. Returns the
+ // context slot index for a given slot name if the slot is present; otherwise
+ // returns a value < 0. The name must be a symbol (canonicalized).
+ // If the slot is present and mode != NULL, sets *mode to the corresponding
+ // mode for that variable.
+ int ContextSlotIndex(String* name, VariableMode* mode);
+
+ // Lookup support for serialized scope info. Returns the
+ // parameter index for a given parameter name if the parameter is present;
+ // otherwise returns a value < 0. The name must be a symbol (canonicalized).
+ int ParameterIndex(String* name);
+
+ // Lookup support for serialized scope info. Returns the
+ // function context slot index if the function name is present (named
+ // function expressions, only), otherwise returns a value < 0. The name
+ // must be a symbol (canonicalized).
+ int FunctionContextSlotIndex(String* name);
+
+ static Handle<SerializedScopeInfo> Create(Scope* scope);
+
+ // Serializes empty scope info.
+ static SerializedScopeInfo* Empty();
+
+ private:
+ Object** ContextEntriesAddr();
+
+ Object** ParameterEntriesAddr();
+
+ Object** StackSlotEntriesAddr();
+};
+
+
// The cache for maps used by normalized (dictionary mode) objects.
// Such maps do not have property descriptors, so a typical program
// needs very limited number of distinct normalized maps.
VariableProxy* Parser::Declare(Handle<String> name,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* fun,
bool resolve,
bool* ok) {
// Similarly, strict mode eval scope does not leak variable declarations to
// the caller's scope so we declare all locals, too.
- Scope* declaration_scope = mode == Variable::LET ? top_scope_
+ Scope* declaration_scope = mode == LET ? top_scope_
: top_scope_->DeclarationScope();
if (declaration_scope->is_function_scope() ||
declaration_scope->is_strict_mode_eval_scope() ||
//
// because the var declaration is hoisted to the function scope where 'x'
// is already bound.
- if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
+ if ((mode != VAR) || (var->mode() != VAR)) {
// We only have vars, consts and lets in declarations.
- ASSERT(var->mode() == Variable::VAR ||
- var->mode() == Variable::CONST ||
- var->mode() == Variable::LET);
+ ASSERT(var->mode() == VAR ||
+ var->mode() == CONST ||
+ var->mode() == LET);
if (harmony_block_scoping_) {
// In harmony mode we treat re-declarations as early errors. See
// ES5 16 for a definition of early errors.
*ok = false;
return NULL;
}
- const char* type = (var->mode() == Variable::VAR) ? "var" :
- (var->mode() == Variable::CONST) ? "const" : "let";
+ const char* type = (var->mode() == VAR) ? "var" :
+ (var->mode() == CONST) ? "const" : "let";
Handle<String> type_string =
isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Expression* expression =
new(zone()) Declaration(proxy, mode, fun, top_scope_));
// For global const variables we bind the proxy to a variable.
- if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
+ if (mode == CONST && declaration_scope->is_global_scope()) {
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
- var = new(zone()) Variable(declaration_scope,
- name,
- Variable::CONST,
- true,
- kind);
+ var = new(zone()) Variable(declaration_scope, name, CONST, true, kind);
}
// If requested and we have a local variable, bind the proxy to the variable
// other functions are setup when entering the surrounding scope.
SharedFunctionInfoLiteral* lit =
new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
- VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
+ VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
return new(zone()) ExpressionStatement(new(zone()) Assignment(
isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
}
// Even if we're not at the top-level of the global or a function
// scope, we treat is as such and introduce the function with it's
// initial value upon entering the corresponding scope.
- Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR;
+ VariableMode mode = harmony_block_scoping_ ? LET : VAR;
Declare(name, mode, fun, true, CHECK_OK);
return EmptyStatement();
}
// VariableDeclarations ::
// ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[',']
- Variable::Mode mode = Variable::VAR;
+ VariableMode mode = VAR;
// True if the binding needs initialization. 'let' and 'const' declared
// bindings are created uninitialized by their declaration nodes and
// need initialization. 'var' declared bindings are always initialized
*ok = false;
return NULL;
}
- mode = Variable::CONST;
+ mode = CONST;
is_const = true;
needs_init = true;
init_op = Token::INIT_CONST;
*ok = false;
return NULL;
}
- mode = Variable::LET;
+ mode = LET;
needs_init = true;
init_op = Token::INIT_LET;
} else {
UNREACHABLE(); // by current callers
}
- Scope* declaration_scope = mode == Variable::LET
+ Scope* declaration_scope = (mode == LET)
? top_scope_ : top_scope_->DeclarationScope();
// The scope of a var/const declared variable anywhere inside a function
// is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
// as the declaration. Thus dynamic lookups are unnecessary even if the
// block scope is inside a with.
if (value != NULL) {
- bool in_with = mode == Variable::VAR ? inside_with() : false;
+ bool in_with = (mode == VAR) ? inside_with() : false;
VariableProxy* proxy =
initialization_scope->NewUnresolved(name, in_with);
Assignment* assignment =
if (top_scope_->is_strict_mode()) {
catch_scope->EnableStrictMode();
}
- Variable::Mode mode = harmony_block_scoping_
- ? Variable::LET : Variable::VAR;
+ VariableMode mode = harmony_block_scoping_ ? LET : VAR;
catch_variable = catch_scope->DeclareLocal(name, mode);
Scope* saved_scope = top_scope_;
}
top_scope_->DeclareParameter(param_name,
- harmony_block_scoping_
- ? Variable::LET
- : Variable::VAR);
+ harmony_block_scoping_ ? LET : VAR);
num_parameters++;
if (num_parameters > kMaxNumFunctionParameters) {
ReportMessageAt(scanner().location(), "too_many_parameters",
void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
// Parser support
- VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
+ VariableProxy* Declare(Handle<String> name, VariableMode mode,
FunctionLiteral* fun,
bool resolve,
bool* ok);
ASSERT(proxy->var()->index() - Context::MIN_CONTEXT_SLOTS ==
context_modes_.length());
context_slots_.Add(FACTORY->empty_symbol());
- context_modes_.Add(Variable::INTERNAL);
+ context_modes_.Add(INTERNAL);
}
}
}
template <class Allocator>
static Object** ReadList(Object** p,
List<Handle<String>, Allocator>* list,
- List<Variable::Mode, Allocator>* modes) {
+ List<VariableMode, Allocator>* modes) {
ASSERT(list->is_empty());
int n;
p = ReadInt(p, &n);
p = ReadSymbol(p, &s);
p = ReadInt(p, &m);
list->Add(s);
- modes->Add(static_cast<Variable::Mode>(m));
+ modes->Add(static_cast<VariableMode>(m));
}
return p;
}
template <class Allocator>
static Object** WriteList(Object** p,
List<Handle<String>, Allocator>* list,
- List<Variable::Mode, Allocator>* modes) {
+ List<VariableMode, Allocator>* modes) {
const int n = list->length();
p = WriteInt(p, n);
for (int i = 0; i < n; i++) {
return -1;
}
-int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
+int SerializedScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
ASSERT(name->IsSymbol());
Isolate* isolate = GetIsolate();
int result = isolate->context_slot_cache()->Lookup(this, name, mode);
ASSERT(((p - p0) & 1) == 0);
int v;
ReadInt(p + 1, &v);
- Variable::Mode mode_value = static_cast<Variable::Mode>(v);
+ VariableMode mode_value = static_cast<VariableMode>(v);
if (mode != NULL) *mode = mode_value;
result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
isolate->context_slot_cache()->Update(this, name, mode_value, result);
p += 2;
}
}
- isolate->context_slot_cache()->Update(this, name, Variable::INTERNAL, -1);
+ isolate->context_slot_cache()->Update(this, name, INTERNAL, -1);
return -1;
}
int ContextSlotCache::Lookup(Object* data,
String* name,
- Variable::Mode* mode) {
+ VariableMode* mode) {
int index = Hash(data, name);
Key& key = keys_[index];
if ((key.data == data) && key.name->Equals(name)) {
void ContextSlotCache::Update(Object* data,
String* name,
- Variable::Mode mode,
+ VariableMode mode,
int slot_index) {
String* symbol;
ASSERT(slot_index > kNotFound);
void ContextSlotCache::ValidateEntry(Object* data,
String* name,
- Variable::Mode mode,
+ VariableMode mode,
int slot_index) {
String* symbol;
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
List<Handle<String>, Allocator > parameters_;
List<Handle<String>, Allocator > stack_slots_;
List<Handle<String>, Allocator > context_slots_;
- List<Variable::Mode, Allocator > context_modes_;
-};
-
-
-// This object provides quick access to scope info details for runtime
-// routines w/o the need to explicitly create a ScopeInfo object.
-class SerializedScopeInfo : public FixedArray {
- public :
-
- static SerializedScopeInfo* cast(Object* object) {
- ASSERT(object->IsSerializedScopeInfo());
- return reinterpret_cast<SerializedScopeInfo*>(object);
- }
-
- // Does this scope call eval?
- bool CallsEval();
-
- // Is this scope a strict mode scope?
- bool IsStrictMode();
-
- // Return the number of stack slots for code.
- int NumberOfStackSlots();
-
- // Return the number of context slots for code.
- int NumberOfContextSlots();
-
- // Return if this has context slots besides MIN_CONTEXT_SLOTS;
- bool HasHeapAllocatedLocals();
-
- // Lookup support for serialized scope info. Returns the
- // the stack slot index for a given slot name if the slot is
- // present; otherwise returns a value < 0. The name must be a symbol
- // (canonicalized).
- int StackSlotIndex(String* name);
-
- // Lookup support for serialized scope info. Returns the
- // context slot index for a given slot name if the slot is present; otherwise
- // returns a value < 0. The name must be a symbol (canonicalized).
- // If the slot is present and mode != NULL, sets *mode to the corresponding
- // mode for that variable.
- int ContextSlotIndex(String* name, Variable::Mode* mode);
-
- // Lookup support for serialized scope info. Returns the
- // parameter index for a given parameter name if the parameter is present;
- // otherwise returns a value < 0. The name must be a symbol (canonicalized).
- int ParameterIndex(String* name);
-
- // Lookup support for serialized scope info. Returns the
- // function context slot index if the function name is present (named
- // function expressions, only), otherwise returns a value < 0. The name
- // must be a symbol (canonicalized).
- int FunctionContextSlotIndex(String* name);
-
- static Handle<SerializedScopeInfo> Create(Scope* scope);
-
- // Serializes empty scope info.
- static SerializedScopeInfo* Empty();
-
- private:
- inline Object** ContextEntriesAddr();
-
- inline Object** ParameterEntriesAddr();
-
- inline Object** StackSlotEntriesAddr();
+ List<VariableMode, Allocator > context_modes_;
};
// If absent, kNotFound is returned.
int Lookup(Object* data,
String* name,
- Variable::Mode* mode);
+ VariableMode* mode);
// Update an element in the cache.
void Update(Object* data,
String* name,
- Variable::Mode mode,
+ VariableMode mode,
int slot_index);
// Clear the cache.
#ifdef DEBUG
void ValidateEntry(Object* data,
String* name,
- Variable::Mode mode,
+ VariableMode mode,
int slot_index);
#endif
};
struct Value {
- Value(Variable::Mode mode, int index) {
+ Value(VariableMode mode, int index) {
ASSERT(ModeField::is_valid(mode));
ASSERT(IndexField::is_valid(index));
value_ = ModeField::encode(mode) | IndexField::encode(index);
uint32_t raw() { return value_; }
- Variable::Mode mode() { return ModeField::decode(value_); }
+ VariableMode mode() { return ModeField::decode(value_); }
int index() { return IndexField::decode(value_); }
// Bit fields in value_ (type, shift, size). Must be public so the
// constants can be embedded in generated code.
- class ModeField: public BitField<Variable::Mode, 0, 3> {};
- class IndexField: public BitField<int, 3, 32-3> {};
+ class ModeField: public BitField<VariableMode, 0, 3> {};
+ class IndexField: public BitField<int, 3, 32-3> {};
private:
uint32_t value_;
};
Variable* VariableMap::Declare(Scope* scope,
Handle<String> name,
- Variable::Mode mode,
+ VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind) {
HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true);
++num_var_or_const_;
Variable* variable = variables_.Declare(this,
catch_variable_name,
- Variable::VAR,
+ VAR,
true, // Valid left-hand side.
Variable::NORMAL);
AllocateHeapSlot(variable);
Variable* var =
variables_.Declare(this,
isolate_->factory()->this_symbol(),
- Variable::VAR,
+ VAR,
false,
Variable::THIS);
var->AllocateTo(Variable::PARAMETER, -1);
// allocated during variable allocation.
variables_.Declare(this,
isolate_->factory()->arguments_symbol(),
- Variable::VAR,
+ VAR,
true,
Variable::ARGUMENTS);
}
ASSERT(scope_info_->StackSlotIndex(*name) < 0);
// Check context slot lookup.
- Variable::Mode mode;
+ VariableMode mode;
int index = scope_info_->ContextSlotIndex(*name, &mode);
if (index < 0) {
// Check parameters.
- mode = Variable::VAR;
+ mode = VAR;
index = scope_info_->ParameterIndex(*name);
if (index < 0) {
// Check the function name.
Variable* Scope::DeclareFunctionVar(Handle<String> name) {
ASSERT(is_function_scope() && function_ == NULL);
Variable* function_var =
- new Variable(this, name, Variable::CONST, true, Variable::NORMAL);
+ new Variable(this, name, CONST, true, Variable::NORMAL);
function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
return function_var;
}
-void Scope::DeclareParameter(Handle<String> name, Variable::Mode mode) {
+void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
ASSERT(!already_resolved());
ASSERT(is_function_scope());
Variable* var =
}
-Variable* Scope::DeclareLocal(Handle<String> name, Variable::Mode mode) {
+Variable* Scope::DeclareLocal(Handle<String> name, VariableMode mode) {
ASSERT(!already_resolved());
// This function handles VAR and CONST modes. DYNAMIC variables are
// introduces during variable allocation, INTERNAL variables are allocated
// explicitly, and TEMPORARY variables are allocated via NewTemporary().
- ASSERT(mode == Variable::VAR ||
- mode == Variable::CONST ||
- mode == Variable::LET);
+ ASSERT(mode == VAR || mode == CONST || mode == LET);
++num_var_or_const_;
return variables_.Declare(this, name, mode, true, Variable::NORMAL);
}
Variable* Scope::DeclareGlobal(Handle<String> name) {
ASSERT(is_global_scope());
- return variables_.Declare(this, name, Variable::DYNAMIC_GLOBAL,
+ return variables_.Declare(this, name, DYNAMIC_GLOBAL,
true,
Variable::NORMAL);
}
ASSERT(!already_resolved());
Variable* var = new Variable(this,
name,
- Variable::TEMPORARY,
+ TEMPORARY,
true,
Variable::NORMAL);
temps_.Add(var);
int length = decls_.length();
for (int i = 0; i < length; i++) {
Declaration* decl = decls_[i];
- if (decl->mode() != Variable::VAR) continue;
+ if (decl->mode() != VAR) continue;
Handle<String> name = decl->proxy()->name();
bool cond = true;
for (Scope* scope = decl->scope(); cond ; scope = scope->outer_scope_) {
// There is a conflict if there exists a non-VAR binding.
Variable* other_var = scope->variables_.Lookup(name);
- if (other_var != NULL && other_var->mode() != Variable::VAR) {
+ if (other_var != NULL && other_var->mode() != VAR) {
return decl;
}
Indent(n1, "// dynamic vars\n");
if (dynamics_ != NULL) {
- PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC));
- PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_LOCAL));
- PrintMap(n1, dynamics_->GetMap(Variable::DYNAMIC_GLOBAL));
+ PrintMap(n1, dynamics_->GetMap(DYNAMIC));
+ PrintMap(n1, dynamics_->GetMap(DYNAMIC_LOCAL));
+ PrintMap(n1, dynamics_->GetMap(DYNAMIC_GLOBAL));
}
// Print inner scopes (disable by providing negative n).
#endif // DEBUG
-Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
+Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
if (dynamics_ == NULL) dynamics_ = new DynamicScopePart();
VariableMap* map = dynamics_->GetMap(mode);
Variable* var = map->Lookup(name);
// Note that we must do a lookup anyway, because if we find one,
// we must mark that variable as potentially accessed from this
// inner scope (the property may not be in the 'with' object).
- var = NonLocal(proxy->name(), Variable::DYNAMIC);
+ var = NonLocal(proxy->name(), DYNAMIC);
} else {
// We are not inside a local 'with' statement.
} else if (scope_inside_with_) {
// If we are inside a with statement we give up and look up
// the variable at runtime.
- var = NonLocal(proxy->name(), Variable::DYNAMIC);
+ var = NonLocal(proxy->name(), DYNAMIC);
} else if (invalidated_local != NULL) {
// No with statements are involved and we found a local
// variable that might be shadowed by eval introduced
// variables.
- var = NonLocal(proxy->name(), Variable::DYNAMIC_LOCAL);
+ var = NonLocal(proxy->name(), DYNAMIC_LOCAL);
var->set_local_if_not_shadowed(invalidated_local);
} else if (outer_scope_is_eval_scope_) {
// variable is global if it is not shadowed by eval-introduced
// variables.
if (context->GlobalIfNotShadowedByEval(proxy->name())) {
- var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
+ var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
} else {
- var = NonLocal(proxy->name(), Variable::DYNAMIC);
+ var = NonLocal(proxy->name(), DYNAMIC);
}
} else {
// is not executed with a call to eval. We know that this
// variable is global unless it is shadowed by eval-introduced
// variables.
- var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
+ var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
}
}
}
//
// Exceptions: temporary variables are never allocated in a context;
// catch-bound variables are always allocated in a context.
- if (var->mode() == Variable::TEMPORARY) return false;
+ if (var->mode() == TEMPORARY) return false;
if (is_catch_scope() || is_block_scope()) return true;
return var->is_accessed_from_inner_scope() ||
scope_calls_eval_ ||
Variable* Declare(Scope* scope,
Handle<String> name,
- Variable::Mode mode,
+ VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind);
// and setup time for scopes that don't need them.
class DynamicScopePart : public ZoneObject {
public:
- VariableMap* GetMap(Variable::Mode mode) {
- int index = mode - Variable::DYNAMIC;
+ VariableMap* GetMap(VariableMode mode) {
+ int index = mode - DYNAMIC;
ASSERT(index >= 0 && index < 3);
return &maps_[index];
}
// Declare a parameter in this scope. When there are duplicated
// parameters the rightmost one 'wins'. However, the implementation
// expects all parameters to be declared and from left to right.
- void DeclareParameter(Handle<String> name, Variable::Mode mode);
+ void DeclareParameter(Handle<String> name, VariableMode mode);
// Declare a local variable in this scope. If the variable has been
// declared before, the previously declared variable is returned.
- Variable* DeclareLocal(Handle<String> name, Variable::Mode mode);
+ Variable* DeclareLocal(Handle<String> name, VariableMode mode);
// Declare an implicit global variable in this scope which must be a
// global scope. The variable was introduced (possibly from an inner
// Create a non-local variable with a given name.
// These variables are looked up dynamically at runtime.
- Variable* NonLocal(Handle<String> name, Variable::Mode mode);
+ Variable* NonLocal(Handle<String> name, VariableMode mode);
// Variable resolution.
Variable* LookupRecursive(Handle<String> name,
// Used to specify if a macro instruction must perform a smi check on tagged
// values.
enum SmiCheckType {
- DONT_DO_SMI_CHECK = 0,
+ DONT_DO_SMI_CHECK,
DO_SMI_CHECK
};
// Used to specify whether a receiver is implicitly or explicitly
// provided to a call.
enum CallKind {
- CALL_AS_METHOD = 0,
+ CALL_AS_METHOD,
CALL_AS_FUNCTION
};
const uint64_t kLastNonNaNInt64 =
(static_cast<uint64_t>(kNaNOrInfinityLowerBoundUpper32) << 32);
+
+enum VariableMode {
+ // User declared variables:
+ VAR, // declared via 'var', and 'function' declarations
+
+ CONST, // declared via 'const' declarations
+
+ LET, // declared via 'let' declarations
+
+ // Variables introduced by the compiler:
+ DYNAMIC, // always require dynamic lookup (we don't know
+ // the declaration)
+
+ DYNAMIC_GLOBAL, // requires dynamic lookup, but we know that the
+ // variable is global unless it has been shadowed
+ // by an eval-introduced variable
+
+ DYNAMIC_LOCAL, // requires dynamic lookup, but we know that the
+ // variable is local and where it is unless it
+ // has been shadowed by an eval-introduced
+ // variable
+
+ INTERNAL, // like VAR, but not user-visible (may or may not
+ // be in a context)
+
+ TEMPORARY // temporary variables (not user-visible), never
+ // in a context
+};
+
} } // namespace v8::internal
#endif // V8_V8GLOBALS_H_
// ----------------------------------------------------------------------------
// Implementation Variable.
-const char* Variable::Mode2String(Mode mode) {
+const char* Variable::Mode2String(VariableMode mode) {
switch (mode) {
case VAR: return "VAR";
case CONST: return "CONST";
Variable::Variable(Scope* scope,
Handle<String> name,
- Mode mode,
+ VariableMode mode,
bool is_valid_LHS,
Kind kind)
: scope_(scope),
class Variable: public ZoneObject {
public:
- enum Mode {
- // User declared variables:
- VAR, // declared via 'var', and 'function' declarations
-
- CONST, // declared via 'const' declarations
-
- LET, // declared via 'let' declarations
-
- // Variables introduced by the compiler:
- DYNAMIC, // always require dynamic lookup (we don't know
- // the declaration)
-
- DYNAMIC_GLOBAL, // requires dynamic lookup, but we know that the
- // variable is global unless it has been shadowed
- // by an eval-introduced variable
-
- DYNAMIC_LOCAL, // requires dynamic lookup, but we know that the
- // variable is local and where it is unless it
- // has been shadowed by an eval-introduced
- // variable
-
- INTERNAL, // like VAR, but not user-visible (may or may not
- // be in a context)
-
- TEMPORARY // temporary variables (not user-visible), never
- // in a context
- };
-
enum Kind {
NORMAL,
THIS,
Variable(Scope* scope,
Handle<String> name,
- Mode mode,
+ VariableMode mode,
bool is_valid_lhs,
Kind kind);
// Printing support
- static const char* Mode2String(Mode mode);
+ static const char* Mode2String(VariableMode mode);
bool IsValidLeftHandSide() { return is_valid_LHS_; }
Scope* scope() const { return scope_; }
Handle<String> name() const { return name_; }
- Mode mode() const { return mode_; }
+ VariableMode mode() const { return mode_; }
bool is_accessed_from_inner_scope() const {
return is_accessed_from_inner_scope_;
}
private:
Scope* scope_;
Handle<String> name_;
- Mode mode_;
+ VariableMode mode_;
Kind kind_;
Location location_;
int index_;
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
int ignored = 0;
- EmitDeclaration(scope()->function(), Variable::CONST, NULL, &ignored);
+ EmitDeclaration(scope()->function(), CONST, NULL, &ignored);
}
VisitDeclarations(scope()->declarations());
}
void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
- Variable::Mode mode,
+ VariableMode mode,
FunctionLiteral* function,
int* global_count) {
// If it was not possible to allocate the variable at compile time, we
Comment cmnt(masm_, "[ Declaration");
VisitForAccumulatorValue(function);
__ movq(StackOperand(variable), result_register());
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
__ movq(StackOperand(variable), kScratchRegister);
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
Comment cmnt(masm_, "[ Declaration");
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
__ movq(ContextOperand(rsi, variable->index()), kScratchRegister);
__ push(rsi);
__ Push(variable->name());
// Declaration nodes are always introduced in one of three modes.
- ASSERT(mode == Variable::VAR ||
- mode == Variable::CONST ||
- mode == Variable::LET);
- PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
+ ASSERT(mode == VAR || mode == CONST || mode == LET);
+ PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE;
__ Push(Smi::FromInt(attr));
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
// must not destroy the current value.
if (function != NULL) {
VisitForStackValue(function);
- } else if (mode == Variable::CONST || mode == Variable::LET) {
+ } else if (mode == CONST || mode == LET) {
__ PushRoot(Heap::kTheHoleValueRootIndex);
} else {
__ Push(Smi::FromInt(0)); // Indicates no initial value.
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
- if (var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (var->mode() == DYNAMIC_GLOBAL) {
EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
__ jmp(done);
- } else if (var->mode() == Variable::DYNAMIC_LOCAL) {
+ } else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == Variable::CONST ||
- local->mode() == Variable::LET) {
+ if (local->mode() == CONST || local->mode() == LET) {
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, done);
- if (local->mode() == Variable::CONST) {
+ if (local->mode() == CONST) {
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- } else { // Variable::LET
+ } else { // LET
__ Push(var->name());
__ CallRuntime(Runtime::kThrowReferenceError, 1);
}
case Variable::LOCAL:
case Variable::CONTEXT: {
Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
- if (var->mode() != Variable::LET && var->mode() != Variable::CONST) {
+ if (var->mode() != LET && var->mode() != CONST) {
context()->Plug(var);
} else {
// Let and const need a read barrier.
GetVar(rax, var);
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &done, Label::kNear);
- if (var->mode() == Variable::LET) {
+ if (var->mode() == LET) {
__ Push(var->name());
__ CallRuntime(Runtime::kThrowReferenceError, 1);
- } else { // Variable::CONST
+ } else { // CONST
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
}
__ bind(&done);
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
- } else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
+ } else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
__ push(rax); // Value.
}
}
- } else if (var->mode() != Variable::CONST) {
+ } else if (var->mode() != CONST) {
// Assignment to var or initializing assignment to let.
if (var->IsStackAllocated() || var->IsContextSlot()) {
MemOperand location = VarOperand(var, rcx);
// context lookup in the runtime system.
Label done;
Variable* var = proxy->var();
- if (!var->IsUnallocated() && var->mode() == Variable::DYNAMIC_GLOBAL) {
+ if (!var->IsUnallocated() && var->mode() == DYNAMIC_GLOBAL) {
Label slow;
EmitLoadGlobalCheckExtensions(var, NOT_INSIDE_TYPEOF, &slow);
// Push the function and resolve eval.