Commit bb97d27a authored by adamk's avatar adamk Committed by Commit bot

Replace BindingFlags enum with InitializationFlag enum

They may have once been different, but they're now redundant with
each other. This simplifies both Context::Lookup and its callers.

Review-Url: https://codereview.chromium.org/2200303002
Cr-Commit-Position: refs/heads/master@{#38261}
parent 83b63c30
......@@ -176,51 +176,14 @@ static Maybe<bool> UnscopableLookup(LookupIterator* it) {
return Just(!blacklist->BooleanValue());
}
static void GetAttributesAndBindingFlags(VariableMode mode,
InitializationFlag init_flag,
PropertyAttributes* attributes,
BindingFlags* binding_flags) {
switch (mode) {
case VAR:
*attributes = NONE;
*binding_flags = BINDING_IS_INITIALIZED;
break;
case LET:
*attributes = NONE;
*binding_flags = (init_flag == kNeedsInitialization)
? BINDING_CHECK_INITIALIZED
: BINDING_IS_INITIALIZED;
break;
case CONST_LEGACY:
DCHECK_EQ(kCreatedInitialized, init_flag);
*attributes = READ_ONLY;
*binding_flags = BINDING_IS_INITIALIZED;
break;
case CONST:
*attributes = READ_ONLY;
*binding_flags = (init_flag == kNeedsInitialization)
? BINDING_CHECK_INITIALIZED
: BINDING_IS_INITIALIZED;
break;
case IMPORT: // TODO(neis): Make sure this is what we want for IMPORT.
case DYNAMIC:
case DYNAMIC_GLOBAL:
case DYNAMIC_LOCAL:
case TEMPORARY:
// Note: Fixed context slots are statically allocated by the compiler.
// Statically allocated variables always have a statically known mode,
// which is the mode with which they were declared when added to the
// scope. Thus, the DYNAMIC mode (which corresponds to dynamically
// declared variables that were introduced through declaration nodes)
// must not appear here.
UNREACHABLE();
break;
}
static PropertyAttributes GetAttributesForMode(VariableMode mode) {
DCHECK(IsDeclaredVariableMode(mode));
return IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
}
Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
int* index, PropertyAttributes* attributes,
BindingFlags* binding_flags,
InitializationFlag* init_flag,
VariableMode* variable_mode) {
Isolate* isolate = GetIsolate();
Handle<Context> context(this, isolate);
......@@ -229,7 +192,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
bool failed_whitelist = false;
*index = kNotFound;
*attributes = ABSENT;
*binding_flags = MISSING_BINDING;
*init_flag = kCreatedInitialized;
*variable_mode = VAR;
if (FLAG_trace_contexts) {
......@@ -270,8 +233,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
*index = r.slot_index;
*variable_mode = r.mode;
GetAttributesAndBindingFlags(r.mode, r.init_flag, attributes,
binding_flags);
*attributes = GetAttributesForMode(r.mode);
return ScriptContextTable::GetContext(script_contexts,
r.context_index);
}
......@@ -326,12 +288,10 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
? context->closure()->shared()->scope_info()
: context->scope_info());
VariableMode mode;
InitializationFlag init_flag;
// TODO(sigurds) Figure out whether maybe_assigned_flag should
// be used to compute binding_flags.
InitializationFlag flag;
MaybeAssignedFlag maybe_assigned_flag;
int slot_index = ScopeInfo::ContextSlotIndex(
scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
int slot_index = ScopeInfo::ContextSlotIndex(scope_info, name, &mode,
&flag, &maybe_assigned_flag);
DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
if (slot_index >= 0) {
if (FLAG_trace_contexts) {
......@@ -340,8 +300,8 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
*index = slot_index;
*variable_mode = mode;
GetAttributesAndBindingFlags(mode, init_flag, attributes,
binding_flags);
*init_flag = flag;
*attributes = GetAttributesForMode(mode);
return context;
}
......@@ -358,7 +318,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
*index = function_index;
*attributes = READ_ONLY;
DCHECK(mode == CONST_LEGACY || mode == CONST);
*binding_flags = BINDING_IS_INITIALIZED;
*init_flag = kCreatedInitialized;
*variable_mode = mode;
return context;
}
......@@ -372,7 +332,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
*index = Context::THROWN_OBJECT_INDEX;
*attributes = NONE;
*binding_flags = BINDING_IS_INITIALIZED;
*init_flag = kCreatedInitialized;
*variable_mode = VAR;
return context;
}
......@@ -391,9 +351,9 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
// Check the original context, but do not follow its context chain.
obj = context->get(WRAPPED_CONTEXT_INDEX);
if (obj->IsContext()) {
Handle<Object> result = Context::cast(obj)->Lookup(
name, DONT_FOLLOW_CHAINS, index, attributes, binding_flags,
variable_mode);
Handle<Object> result =
Context::cast(obj)->Lookup(name, DONT_FOLLOW_CHAINS, index,
attributes, init_flag, variable_mode);
if (!result.is_null()) return result;
}
// Check whitelist. Names that do not pass whitelist shall only resolve
......
......@@ -25,39 +25,6 @@ enum ContextLookupFlags {
};
// ES5 10.2 defines lexical environments with mutable and immutable bindings.
// Immutable bindings have two states, initialized and uninitialized, and
// their state is changed by the InitializeImmutableBinding method. The
// BindingFlags enum represents information if a binding has definitely been
// initialized. A mutable binding does not need to be checked and thus has
// the BindingFlag BINDING_IS_INITIALIZED.
//
// There is one possibility for legacy immutable bindings:
// * The function name of a named function literal. The binding is immediately
// initialized when entering the function and thus does not need to be
// checked. it gets the BindingFlag BINDING_IS_INITIALIZED.
//
// The harmony proposal for block scoped bindings also introduces the
// uninitialized state for mutable bindings.
// * A 'let' declared variable. They are initialized when evaluating the
// corresponding declaration statement. They need to be checked for being
// initialized and thus get the flag BINDING_CHECK_INITIALIZED.
// * A 'var' declared variable. It is initialized immediately upon creation
// and thus doesn't need to be checked. It gets the flag
// BINDING_IS_INITIALIZED.
// * Catch bound variables, function parameters and variables introduced by
// function declarations are initialized immediately and do not need to be
// checked. Thus they get the flag BINDING_IS_INITIALIZED.
// Accessing an uninitialized binding produces a reference error.
//
// In V8 uninitialized bindings are set to the hole value upon creation and set
// to a different value upon initialization.
enum BindingFlags {
BINDING_IS_INITIALIZED,
BINDING_CHECK_INITIALIZED,
MISSING_BINDING
};
// Heap-allocated activation contexts.
//
// Contexts are implemented as FixedArray objects; the Context
......@@ -507,7 +474,7 @@ class Context: public FixedArray {
// always ABSENT.
Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags,
int* index, PropertyAttributes* attributes,
BindingFlags* binding_flags,
InitializationFlag* init_flag,
VariableMode* variable_mode);
// Code generation support.
......
......@@ -266,11 +266,11 @@ Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name,
int index;
PropertyAttributes attributes;
BindingFlags binding_flags;
InitializationFlag init_flag;
VariableMode mode;
// Check for a conflict with a lexically scoped variable
context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &binding_flags,
context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &init_flag,
&mode);
if (attributes != ABSENT && IsLexicalVariableMode(mode)) {
// ES#sec-evaldeclarationinstantiation 5.a.i.1:
......@@ -283,7 +283,7 @@ Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name,
}
Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
&attributes, &binding_flags, &mode);
&attributes, &init_flag, &mode);
DCHECK(!isolate->has_pending_exception());
Handle<JSObject> object;
......@@ -772,10 +772,10 @@ RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
int index;
PropertyAttributes attributes;
BindingFlags flags;
InitializationFlag flag;
VariableMode mode;
Handle<Object> holder = isolate->context()->Lookup(
name, FOLLOW_CHAINS, &index, &attributes, &flags, &mode);
name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
// If the slot was not found the result is true.
if (holder.is_null()) {
......@@ -808,10 +808,10 @@ MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
int index;
PropertyAttributes attributes;
BindingFlags flags;
InitializationFlag flag;
VariableMode mode;
Handle<Object> holder = isolate->context()->Lookup(
name, FOLLOW_CHAINS, &index, &attributes, &flags, &mode);
name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
if (isolate->has_pending_exception()) return MaybeHandle<Object>();
if (index != Context::kNotFound) {
......@@ -821,22 +821,14 @@ MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
Handle<Object> receiver = isolate->factory()->undefined_value();
Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
// Check for uninitialized bindings.
switch (flags) {
case BINDING_CHECK_INITIALIZED:
if (value->IsTheHole(isolate)) {
THROW_NEW_ERROR(isolate,
NewReferenceError(MessageTemplate::kNotDefined, name),
Object);
}
// FALLTHROUGH
case BINDING_IS_INITIALIZED:
DCHECK(!value->IsTheHole(isolate));
if (receiver_return) *receiver_return = receiver;
return value;
case MISSING_BINDING:
break;
if (flag == kNeedsInitialization && value->IsTheHole(isolate)) {
THROW_NEW_ERROR(isolate,
NewReferenceError(MessageTemplate::kNotDefined, name),
Object);
}
UNREACHABLE();
DCHECK(!value->IsTheHole(isolate));
if (receiver_return) *receiver_return = receiver;
return value;
}
// Otherwise, if the slot was found the holder is a context extension
......@@ -912,10 +904,10 @@ MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
int index;
PropertyAttributes attributes;
BindingFlags flags;
InitializationFlag flag;
VariableMode mode;
Handle<Object> holder =
context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags, &mode);
context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
if (holder.is_null()) {
// In case of JSProxy, an exception might have been thrown.
if (isolate->has_pending_exception()) return MaybeHandle<Object>();
......@@ -923,7 +915,7 @@ MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
// The property was found in a context slot.
if (index != Context::kNotFound) {
if (flags == BINDING_CHECK_INITIALIZED &&
if (flag == kNeedsInitialization &&
Handle<Context>::cast(holder)->is_the_hole(index)) {
THROW_NEW_ERROR(isolate,
NewReferenceError(MessageTemplate::kNotDefined, name),
......
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