Commit 58123bff authored by keuchel@chromium.org's avatar keuchel@chromium.org

Remove some unnecessary binding initialization checks.

This depends on http://codereview.chromium.org/8352039/ .

Review URL: http://codereview.chromium.org/8423005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9869 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 7385fef2
......@@ -710,8 +710,8 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
Variable* variable = proxy->var();
bool binding_needs_init =
mode == CONST || mode == CONST_HARMONY || mode == LET;
bool binding_needs_init = (function == NULL) &&
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
......
......@@ -146,7 +146,8 @@ Handle<Object> Context::Lookup(Handle<String> name,
ScopeInfo::cast(context->extension()), isolate);
}
VariableMode mode;
int slot_index = scope_info->ContextSlotIndex(*name, &mode);
InitializationFlag init_flag;
int slot_index = scope_info->ContextSlotIndex(*name, &mode, &init_flag);
ASSERT(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
if (slot_index >= 0) {
if (FLAG_trace_contexts) {
......@@ -168,15 +169,19 @@ Handle<Object> Context::Lookup(Handle<String> name,
break;
case LET:
*attributes = NONE;
*binding_flags = MUTABLE_CHECK_INITIALIZED;
*binding_flags = (init_flag == kNeedsInitialization)
? MUTABLE_CHECK_INITIALIZED : MUTABLE_IS_INITIALIZED;
break;
case CONST:
*attributes = READ_ONLY;
*binding_flags = IMMUTABLE_CHECK_INITIALIZED;
*binding_flags = (init_flag == kNeedsInitialization)
? IMMUTABLE_CHECK_INITIALIZED : IMMUTABLE_IS_INITIALIZED;
break;
case CONST_HARMONY:
*attributes = READ_ONLY;
*binding_flags = IMMUTABLE_CHECK_INITIALIZED_HARMONY;
*binding_flags = (init_flag == kNeedsInitialization)
? IMMUTABLE_CHECK_INITIALIZED_HARMONY :
IMMUTABLE_IS_INITIALIZED_HARMONY;
break;
case DYNAMIC:
case DYNAMIC_GLOBAL:
......@@ -252,7 +257,8 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
// Check non-parameter locals.
Handle<ScopeInfo> scope_info(context->closure()->shared()->scope_info());
VariableMode mode;
int index = scope_info->ContextSlotIndex(*name, &mode);
InitializationFlag init_flag;
int index = scope_info->ContextSlotIndex(*name, &mode, &init_flag);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (index >= 0) return false;
......
......@@ -681,8 +681,8 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
Variable* variable = proxy->var();
bool binding_needs_init =
mode == CONST || mode == CONST_HARMONY || mode == LET;
bool binding_needs_init = (function == NULL) &&
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
......
......@@ -720,8 +720,8 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
Variable* variable = proxy->var();
bool binding_needs_init =
mode == CONST || mode == CONST_HARMONY || mode == LET;
bool binding_needs_init = (function == NULL) &&
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
......
......@@ -3169,6 +3169,9 @@ class ScopeInfo : public FixedArray {
// Return the mode of the given context local.
VariableMode ContextLocalMode(int var);
// Return the initialization flag of the given context local.
InitializationFlag ContextLocalInitFlag(int var);
// 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
......@@ -3180,7 +3183,9 @@ class ScopeInfo : public FixedArray {
// 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);
int ContextSlotIndex(String* name,
VariableMode* mode,
InitializationFlag* init_flag);
// Lookup support for serialized scope info. Returns the
// parameter index for a given parameter name if the parameter is present;
......@@ -3256,10 +3261,11 @@ class ScopeInfo : public FixedArray {
// index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
// context local, so in total this part occupies ContextLocalCount() slots
// in the array.
// 4. ContextLocalModeEntries:
// Contains the variable modes corresponding to the context locals in
// ContextLocalNameEntries. One slot is used per context local, so in total
// this part occupies ContextLocalCount() slots in the array.
// 4. ContextLocalInfoEntries:
// Contains the variable modes and initialization flags corresponding to
// the context locals in ContextLocalNameEntries. One slot is used per
// context local, so in total this part occupies ContextLocalCount()
// slots in the array.
// 5. FunctionNameEntryIndex:
// If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array
......@@ -3268,7 +3274,7 @@ class ScopeInfo : public FixedArray {
int ParameterEntriesIndex();
int StackLocalEntriesIndex();
int ContextLocalNameEntriesIndex();
int ContextLocalModeEntriesIndex();
int ContextLocalInfoEntriesIndex();
int FunctionNameEntryIndex();
// Location of the function variable for named function expressions.
......@@ -3285,6 +3291,11 @@ class ScopeInfo : public FixedArray {
class StrictModeField: public BitField<bool, 4, 1> {};
class FunctionVariableField: public BitField<FunctionVariableInfo, 5, 2> {};
class FunctionVariableMode: public BitField<VariableMode, 7, 3> {};
// BitFields representing the encoded information for context locals in the
// ContextLocalInfoEntries part.
class ContextLocalMode: public BitField<VariableMode, 0, 3> {};
class ContextLocalInitFlag: public BitField<InitializationFlag, 3, 1> {};
};
......
......@@ -1385,7 +1385,9 @@ VariableProxy* Parser::Declare(Handle<String> name,
var = declaration_scope->LocalLookup(name);
if (var == NULL) {
// Declare the name.
var = declaration_scope->DeclareLocal(name, mode);
InitializationFlag init_flag = (fun != NULL || mode == VAR)
? kCreatedInitialized : kNeedsInitialization;
var = declaration_scope->DeclareLocal(name, mode, init_flag);
} else {
// The name was declared in this scope before; check for conflicting
// re-declarations. We have a conflict if either of the declarations is
......@@ -1452,7 +1454,12 @@ VariableProxy* Parser::Declare(Handle<String> name,
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, CONST, true, kind);
var = new(zone()) Variable(declaration_scope,
name,
CONST,
true,
kind,
kNeedsInitialization);
}
// If requested and we have a local variable, bind the proxy to the variable
......@@ -2283,7 +2290,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
if (peek() == Token::LBRACE) {
Target target(&this->target_stack_, &catch_collector);
VariableMode mode = harmony_scoping_ ? LET : VAR;
catch_variable = catch_scope->DeclareLocal(name, mode);
catch_variable =
catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
SaveScope save_scope(this, catch_scope);
catch_block = ParseBlock(NULL, CHECK_OK);
......
......@@ -10794,9 +10794,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
for (; i < scope_info->LocalCount(); ++i) {
Handle<String> name(scope_info->LocalName(i));
VariableMode mode;
InitializationFlag init_flag;
locals->set(i * 2, *name);
locals->set(i * 2 + 1,
context->get(scope_info->ContextSlotIndex(*name, &mode)));
locals->set(i * 2 + 1, context->get(
scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
}
}
......@@ -10970,8 +10971,9 @@ static bool CopyContextLocalsToScopeObject(
// Fill all context locals to the context extension.
for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
VariableMode mode;
InitializationFlag init_flag;
int context_index = scope_info->ContextSlotIndex(
scope_info->ContextLocalName(i), &mode);
scope_info->ContextLocalName(i), &mode, &init_flag);
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
......@@ -11941,8 +11943,9 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
if (scope_info->HasHeapAllocatedLocals()) {
VariableMode mode;
InitializationFlag init_flag;
index = scope_info->ContextSlotIndex(
isolate->heap()->arguments_symbol(), &mode);
isolate->heap()->arguments_symbol(), &mode, &init_flag);
if (index != -1) {
return Handle<Object>(function_context->get(index), isolate);
}
......
......@@ -148,10 +148,13 @@ Handle<ScopeInfo> ScopeInfo::Create(Scope* scope) {
scope_info->set(index++, *context_locals[i]->name());
}
// Add context locals' modes.
ASSERT(index == scope_info->ContextLocalModeEntriesIndex());
// Add context locals' info.
ASSERT(index == scope_info->ContextLocalInfoEntriesIndex());
for (int i = 0; i < context_local_count; ++i) {
scope_info->set(index++, Smi::FromInt(context_locals[i]->mode()));
Variable* var = context_locals[i];
uint32_t value = ContextLocalMode::encode(var->mode()) |
ContextLocalInitFlag::encode(var->initialization_flag());
scope_info->set(index++, Smi::FromInt(value));
}
// If present, add the function variable name and its index.
......@@ -294,8 +297,17 @@ String* ScopeInfo::ContextLocalName(int var) {
VariableMode ScopeInfo::ContextLocalMode(int var) {
ASSERT(0 <= var && var < ContextLocalCount());
int info_index = ContextLocalModeEntriesIndex() + var;
return static_cast<VariableMode>(Smi::cast(get(info_index))->value());
int info_index = ContextLocalInfoEntriesIndex() + var;
int value = Smi::cast(get(info_index))->value();
return ContextLocalMode::decode(value);
}
InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) {
ASSERT(0 <= var && var < ContextLocalCount());
int info_index = ContextLocalInfoEntriesIndex() + var;
int value = Smi::cast(get(info_index))->value();
return ContextLocalInitFlag::decode(value);
}
......@@ -314,12 +326,15 @@ int ScopeInfo::StackSlotIndex(String* name) {
}
int ScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
int ScopeInfo::ContextSlotIndex(String* name,
VariableMode* mode,
InitializationFlag* init_flag) {
ASSERT(name->IsSymbol());
ASSERT(mode != NULL);
ASSERT(init_flag != NULL);
if (length() > 0) {
ContextSlotCache* context_slot_cache = GetIsolate()->context_slot_cache();
int result = context_slot_cache->Lookup(this, name, mode);
int result = context_slot_cache->Lookup(this, name, mode, init_flag);
if (result != ContextSlotCache::kNotFound) {
ASSERT(result < ContextLength());
return result;
......@@ -331,13 +346,14 @@ int ScopeInfo::ContextSlotIndex(String* name, VariableMode* mode) {
if (name == get(i)) {
int var = i - start;
*mode = ContextLocalMode(var);
*init_flag = ContextLocalInitFlag(var);
result = Context::MIN_CONTEXT_SLOTS + var;
context_slot_cache->Update(this, name, *mode, result);
context_slot_cache->Update(this, name, *mode, *init_flag, result);
ASSERT(result < ContextLength());
return result;
}
}
context_slot_cache->Update(this, name, INTERNAL, -1);
context_slot_cache->Update(this, name, INTERNAL, kNeedsInitialization, -1);
}
return -1;
}
......@@ -393,13 +409,13 @@ int ScopeInfo::ContextLocalNameEntriesIndex() {
}
int ScopeInfo::ContextLocalModeEntriesIndex() {
int ScopeInfo::ContextLocalInfoEntriesIndex() {
return ContextLocalNameEntriesIndex() + ContextLocalCount();
}
int ScopeInfo::FunctionNameEntryIndex() {
return ContextLocalModeEntriesIndex() + ContextLocalCount();
return ContextLocalInfoEntriesIndex() + ContextLocalCount();
}
......@@ -413,12 +429,14 @@ int ContextSlotCache::Hash(Object* data, String* name) {
int ContextSlotCache::Lookup(Object* data,
String* name,
VariableMode* mode) {
VariableMode* mode,
InitializationFlag* init_flag) {
int index = Hash(data, name);
Key& key = keys_[index];
if ((key.data == data) && key.name->Equals(name)) {
Value result(values_[index]);
if (mode != NULL) *mode = result.mode();
if (init_flag != NULL) *init_flag = result.initialization_flag();
return result.index() + kNotFound;
}
return kNotFound;
......@@ -428,6 +446,7 @@ int ContextSlotCache::Lookup(Object* data,
void ContextSlotCache::Update(Object* data,
String* name,
VariableMode mode,
InitializationFlag init_flag,
int slot_index) {
String* symbol;
ASSERT(slot_index > kNotFound);
......@@ -437,9 +456,9 @@ void ContextSlotCache::Update(Object* data,
key.data = data;
key.name = symbol;
// Please note value only takes a uint as index.
values_[index] = Value(mode, slot_index - kNotFound).raw();
values_[index] = Value(mode, init_flag, slot_index - kNotFound).raw();
#ifdef DEBUG
ValidateEntry(data, name, mode, slot_index);
ValidateEntry(data, name, mode, init_flag, slot_index);
#endif
}
}
......@@ -455,6 +474,7 @@ void ContextSlotCache::Clear() {
void ContextSlotCache::ValidateEntry(Object* data,
String* name,
VariableMode mode,
InitializationFlag init_flag,
int slot_index) {
String* symbol;
if (HEAP->LookupSymbolIfExists(name, &symbol)) {
......@@ -464,6 +484,7 @@ void ContextSlotCache::ValidateEntry(Object* data,
ASSERT(key.name->Equals(name));
Value result(values_[index]);
ASSERT(result.mode() == mode);
ASSERT(result.initialization_flag() == init_flag);
ASSERT(result.index() + kNotFound == slot_index);
}
}
......
......@@ -45,12 +45,14 @@ class ContextSlotCache {
// If absent, kNotFound is returned.
int Lookup(Object* data,
String* name,
VariableMode* mode);
VariableMode* mode,
InitializationFlag* init_flag);
// Update an element in the cache.
void Update(Object* data,
String* name,
VariableMode mode,
InitializationFlag init_flag,
int slot_index);
// Clear the cache.
......@@ -73,6 +75,7 @@ class ContextSlotCache {
void ValidateEntry(Object* data,
String* name,
VariableMode mode,
InitializationFlag init_flag,
int slot_index);
#endif
......@@ -83,11 +86,17 @@ class ContextSlotCache {
};
struct Value {
Value(VariableMode mode, int index) {
Value(VariableMode mode,
InitializationFlag init_flag,
int index) {
ASSERT(ModeField::is_valid(mode));
ASSERT(InitField::is_valid(init_flag));
ASSERT(IndexField::is_valid(index));
value_ = ModeField::encode(mode) | IndexField::encode(index);
value_ = ModeField::encode(mode) |
IndexField::encode(index) |
InitField::encode(init_flag);
ASSERT(mode == this->mode());
ASSERT(init_flag == this->initialization_flag());
ASSERT(index == this->index());
}
......@@ -97,12 +106,18 @@ class ContextSlotCache {
VariableMode mode() { return ModeField::decode(value_); }
InitializationFlag initialization_flag() {
return InitField::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<VariableMode, 0, 3> {};
class IndexField: public BitField<int, 3, 32-3> {};
class ModeField: public BitField<VariableMode, 0, 3> {};
class InitField: public BitField<InitializationFlag, 3, 1> {};
class IndexField: public BitField<int, 4, 32-4> {};
private:
uint32_t value_;
};
......
......@@ -80,16 +80,23 @@ VariableMap::VariableMap() : HashMap(Match, &LocalsMapAllocator, 8) {}
VariableMap::~VariableMap() {}
Variable* VariableMap::Declare(Scope* scope,
Handle<String> name,
VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind) {
Variable* VariableMap::Declare(
Scope* scope,
Handle<String> name,
VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind,
InitializationFlag initialization_flag) {
HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true);
if (p->value == NULL) {
// The variable has not been declared yet -> insert it.
ASSERT(p->key == name.location());
p->value = new Variable(scope, name, mode, is_valid_lhs, kind);
p->value = new Variable(scope,
name,
mode,
is_valid_lhs,
kind,
initialization_flag);
}
return reinterpret_cast<Variable*>(p->value);
}
......@@ -162,7 +169,8 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
catch_variable_name,
VAR,
true, // Valid left-hand side.
Variable::NORMAL);
Variable::NORMAL,
kCreatedInitialized);
AllocateHeapSlot(variable);
}
......@@ -290,7 +298,8 @@ void Scope::Initialize() {
isolate_->factory()->this_symbol(),
VAR,
false,
Variable::THIS);
Variable::THIS,
kCreatedInitialized);
var->AllocateTo(Variable::PARAMETER, -1);
receiver_ = var;
} else {
......@@ -306,7 +315,8 @@ void Scope::Initialize() {
isolate_->factory()->arguments_symbol(),
VAR,
true,
Variable::ARGUMENTS);
Variable::ARGUMENTS,
kCreatedInitialized);
}
}
......@@ -355,10 +365,12 @@ Variable* Scope::LocalLookup(Handle<String> name) {
// Check context slot lookup.
VariableMode mode;
int index = scope_info_->ContextSlotIndex(*name, &mode);
InitializationFlag init_flag;
int index = scope_info_->ContextSlotIndex(*name, &mode, &init_flag);
if (index < 0) {
// Check parameters.
mode = VAR;
init_flag = kCreatedInitialized;
index = scope_info_->ParameterIndex(*name);
if (index < 0) {
// Check the function name.
......@@ -368,7 +380,12 @@ Variable* Scope::LocalLookup(Handle<String> name) {
}
Variable* var =
variables_.Declare(this, name, mode, true, Variable::NORMAL);
variables_.Declare(this,
name,
mode,
true,
Variable::NORMAL,
init_flag);
var->AllocateTo(Variable::CONTEXT, index);
return var;
}
......@@ -387,8 +404,8 @@ Variable* Scope::Lookup(Handle<String> name) {
Variable* Scope::DeclareFunctionVar(Handle<String> name, VariableMode mode) {
ASSERT(is_function_scope() && function_ == NULL);
Variable* function_var =
new Variable(this, name, mode, true, Variable::NORMAL);
Variable* function_var = new Variable(
this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
function_ = new(isolate_->zone()) VariableProxy(isolate_, function_var);
return function_var;
}
......@@ -397,13 +414,15 @@ Variable* Scope::DeclareFunctionVar(Handle<String> name, VariableMode mode) {
void Scope::DeclareParameter(Handle<String> name, VariableMode mode) {
ASSERT(!already_resolved());
ASSERT(is_function_scope());
Variable* var =
variables_.Declare(this, name, mode, true, Variable::NORMAL);
Variable* var = variables_.Declare(
this, name, mode, true, Variable::NORMAL, kCreatedInitialized);
params_.Add(var);
}
Variable* Scope::DeclareLocal(Handle<String> name, VariableMode mode) {
Variable* Scope::DeclareLocal(Handle<String> name,
VariableMode mode,
InitializationFlag init_flag) {
ASSERT(!already_resolved());
// This function handles VAR and CONST modes. DYNAMIC variables are
// introduces during variable allocation, INTERNAL variables are allocated
......@@ -413,15 +432,19 @@ Variable* Scope::DeclareLocal(Handle<String> name, VariableMode mode) {
mode == CONST_HARMONY ||
mode == LET);
++num_var_or_const_;
return variables_.Declare(this, name, mode, true, Variable::NORMAL);
return
variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag);
}
Variable* Scope::DeclareGlobal(Handle<String> name) {
ASSERT(is_global_scope());
return variables_.Declare(this, name, DYNAMIC_GLOBAL,
return variables_.Declare(this,
name,
DYNAMIC_GLOBAL,
true,
Variable::NORMAL);
Variable::NORMAL,
kCreatedInitialized);
}
......@@ -455,7 +478,8 @@ Variable* Scope::NewTemporary(Handle<String> name) {
name,
TEMPORARY,
true,
Variable::NORMAL);
Variable::NORMAL,
kCreatedInitialized);
temps_.Add(var);
return var;
}
......@@ -784,7 +808,14 @@ Variable* Scope::NonLocal(Handle<String> name, VariableMode mode) {
Variable* var = map->Lookup(name);
if (var == NULL) {
// Declare a new non-local.
var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
InitializationFlag init_flag = (mode == VAR)
? kCreatedInitialized : kNeedsInitialization;
var = map->Declare(NULL,
name,
mode,
true,
Variable::NORMAL,
init_flag);
// Allocate it by giving it a dynamic lookup.
var->AllocateTo(Variable::LOOKUP, -1);
}
......
......@@ -48,7 +48,8 @@ class VariableMap: public HashMap {
Handle<String> name,
VariableMode mode,
bool is_valid_lhs,
Variable::Kind kind);
Variable::Kind kind,
InitializationFlag initialization_flag);
Variable* Lookup(Handle<String> name);
};
......@@ -127,7 +128,9 @@ class Scope: public ZoneObject {
// 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, VariableMode mode);
Variable* DeclareLocal(Handle<String> name,
VariableMode mode,
InitializationFlag init_flag);
// Declare an implicit global variable in this scope which must be a
// global scope. The variable was introduced (possibly from an inner
......
......@@ -549,6 +549,43 @@ enum VariableMode {
};
// ES6 Draft Rev3 10.2 specifies declarative environment records with mutable
// and immutable bindings that can be in two states: initialized and
// uninitialized. In ES5 only immutable bindings have these two states. When
// accessing a binding, it needs to be checked for initialization. However in
// the following cases the binding is initialized immediately after creation
// so the initialization check can always be skipped:
// 1. Var declared local variables.
// var foo;
// 2. A local variable introduced by a function declaration.
// function foo() {}
// 3. Parameters
// function x(foo) {}
// 4. Catch bound variables.
// try {} catch (foo) {}
// 6. Function variables of named function expressions.
// var x = function foo() {}
// 7. Implicit binding of 'this'.
// 8. Implicit binding of 'arguments' in functions.
//
// ES5 specified object environment records which are introduced by ES elements
// such as Program and WithStatement that associate identifier bindings with the
// properties of some object. In the specification only mutable bindings exist
// (which may be non-writable) and have no distinct initialization step. However
// V8 allows const declarations in global code with distinct creation and
// initialization steps which are represented by non-writable properties in the
// global object. As a result also these bindings need to be checked for
// initialization.
//
// The following enum specifies a flag that indicates if the binding needs a
// distinct initialization step (kNeedsInitialization) or if the binding is
// immediately initialized upon creation (kCreatedInitialized).
enum InitializationFlag {
kNeedsInitialization,
kCreatedInitialized
};
enum ClearExceptionFlag {
KEEP_EXCEPTION,
CLEAR_EXCEPTION
......
......@@ -58,7 +58,8 @@ Variable::Variable(Scope* scope,
Handle<String> name,
VariableMode mode,
bool is_valid_LHS,
Kind kind)
Kind kind,
InitializationFlag initialization_flag)
: scope_(scope),
name_(name),
mode_(mode),
......@@ -68,9 +69,12 @@ Variable::Variable(Scope* scope,
local_if_not_shadowed_(NULL),
is_valid_LHS_(is_valid_LHS),
is_accessed_from_inner_scope_(false),
is_used_(false) {
// names must be canonicalized for fast equality checks
is_used_(false),
initialization_flag_(initialization_flag) {
// Names must be canonicalized for fast equality checks.
ASSERT(name->IsSymbol());
// Var declared variables never need initialization.
ASSERT(!(mode == VAR && initialization_flag == kNeedsInitialization));
}
......
......@@ -77,7 +77,8 @@ class Variable: public ZoneObject {
Handle<String> name,
VariableMode mode,
bool is_valid_lhs,
Kind kind);
Kind kind,
InitializationFlag initialization_flag);
// Printing support
static const char* Mode2String(VariableMode mode);
......@@ -123,9 +124,7 @@ class Variable: public ZoneObject {
mode_ == CONST_HARMONY);
}
bool binding_needs_init() const {
return (mode_ == LET ||
mode_ == CONST ||
mode_ == CONST_HARMONY);
return initialization_flag_ == kNeedsInitialization;
}
bool is_global() const;
......@@ -148,6 +147,9 @@ class Variable: public ZoneObject {
Location location() const { return location_; }
int index() const { return index_; }
InitializationFlag initialization_flag() const {
return initialization_flag_;
}
void AllocateTo(Location location, int index) {
location_ = location;
......@@ -174,6 +176,7 @@ class Variable: public ZoneObject {
// Usage info.
bool is_accessed_from_inner_scope_; // set by variable resolver
bool is_used_;
InitializationFlag initialization_flag_;
};
......
......@@ -676,8 +676,8 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy,
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
Variable* variable = proxy->var();
bool binding_needs_init =
mode == CONST || mode == CONST_HARMONY || mode == LET;
bool binding_needs_init = (function == NULL) &&
(mode == CONST || mode == CONST_HARMONY || mode == LET);
switch (variable->location()) {
case Variable::UNALLOCATED:
++(*global_count);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment