1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_AST_VARIABLES_H_ 6 #define V8_AST_VARIABLES_H_ 7 8 #include "src/ast/ast-value-factory.h" 9 #include "src/globals.h" 10 #include "src/zone/zone.h" 11 12 namespace v8 { 13 namespace internal { 14 15 // The AST refers to variables via VariableProxies - placeholders for the actual 16 // variables. Variables themselves are never directly referred to from the AST, 17 // they are maintained by scopes, and referred to from VariableProxies and Slots 18 // after binding and variable allocation. 19 class Variable final : public ZoneObject { 20 public: 21 Variable(Scope* scope, const AstRawString* name, VariableMode mode, 22 VariableKind kind, InitializationFlag initialization_flag, 23 MaybeAssignedFlag maybe_assigned_flag = kNotAssigned); 24 25 // The source code for an eval() call may refer to a variable that is 26 // in an outer scope about which we don't know anything (it may not 27 // be the script scope). scope() is NULL in that case. Currently the 28 // scope is only used to follow the context chain length. scope()29 Scope* scope() const { return scope_; } 30 31 // This is for adjusting the scope of temporaries used when desugaring 32 // parameter initializers. set_scope(Scope * scope)33 void set_scope(Scope* scope) { scope_ = scope; } 34 name()35 Handle<String> name() const { return name_->string(); } raw_name()36 const AstRawString* raw_name() const { return name_; } mode()37 VariableMode mode() const { return VariableModeField::decode(bit_field_); } has_forced_context_allocation()38 bool has_forced_context_allocation() const { 39 return ForceContextAllocationField::decode(bit_field_); 40 } ForceContextAllocation()41 void ForceContextAllocation() { 42 DCHECK(IsUnallocated() || IsContextSlot() || 43 location() == VariableLocation::MODULE); 44 bit_field_ = ForceContextAllocationField::update(bit_field_, true); 45 } is_used()46 bool is_used() { return IsUsedField::decode(bit_field_); } set_is_used()47 void set_is_used() { bit_field_ = IsUsedField::update(bit_field_, true); } maybe_assigned()48 MaybeAssignedFlag maybe_assigned() const { 49 return MaybeAssignedFlagField::decode(bit_field_); 50 } set_maybe_assigned()51 void set_maybe_assigned() { 52 bit_field_ = MaybeAssignedFlagField::update(bit_field_, kMaybeAssigned); 53 } 54 initializer_position()55 int initializer_position() { return initializer_position_; } set_initializer_position(int pos)56 void set_initializer_position(int pos) { initializer_position_ = pos; } 57 IsUnallocated()58 bool IsUnallocated() const { 59 return location() == VariableLocation::UNALLOCATED; 60 } IsParameter()61 bool IsParameter() const { return location() == VariableLocation::PARAMETER; } IsStackLocal()62 bool IsStackLocal() const { return location() == VariableLocation::LOCAL; } IsStackAllocated()63 bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); } IsContextSlot()64 bool IsContextSlot() const { return location() == VariableLocation::CONTEXT; } IsLookupSlot()65 bool IsLookupSlot() const { return location() == VariableLocation::LOOKUP; } 66 bool IsGlobalObjectProperty() const; 67 is_dynamic()68 bool is_dynamic() const { return IsDynamicVariableMode(mode()); } binding_needs_init()69 bool binding_needs_init() const { 70 DCHECK(initialization_flag() != kNeedsInitialization || 71 IsLexicalVariableMode(mode())); 72 return initialization_flag() == kNeedsInitialization; 73 } throw_on_const_assignment(LanguageMode language_mode)74 bool throw_on_const_assignment(LanguageMode language_mode) const { 75 return kind() != SLOPPY_FUNCTION_NAME_VARIABLE || is_strict(language_mode); 76 } 77 is_function()78 bool is_function() const { return kind() == FUNCTION_VARIABLE; } is_this()79 bool is_this() const { return kind() == THIS_VARIABLE; } is_sloppy_function_name()80 bool is_sloppy_function_name() const { 81 return kind() == SLOPPY_FUNCTION_NAME_VARIABLE; 82 } 83 local_if_not_shadowed()84 Variable* local_if_not_shadowed() const { 85 DCHECK(mode() == DYNAMIC_LOCAL && local_if_not_shadowed_ != NULL); 86 return local_if_not_shadowed_; 87 } 88 set_local_if_not_shadowed(Variable * local)89 void set_local_if_not_shadowed(Variable* local) { 90 local_if_not_shadowed_ = local; 91 } 92 location()93 VariableLocation location() const { 94 return LocationField::decode(bit_field_); 95 } kind()96 VariableKind kind() const { return VariableKindField::decode(bit_field_); } initialization_flag()97 InitializationFlag initialization_flag() const { 98 return InitializationFlagField::decode(bit_field_); 99 } 100 index()101 int index() const { return index_; } 102 IsExport()103 bool IsExport() const { 104 DCHECK_EQ(location(), VariableLocation::MODULE); 105 DCHECK_NE(index(), 0); 106 return index() > 0; 107 } 108 AllocateTo(VariableLocation location,int index)109 void AllocateTo(VariableLocation location, int index) { 110 DCHECK(IsUnallocated() || 111 (this->location() == location && this->index() == index)); 112 DCHECK_IMPLIES(location == VariableLocation::MODULE, index != 0); 113 bit_field_ = LocationField::update(bit_field_, location); 114 DCHECK_EQ(location, this->location()); 115 index_ = index; 116 } 117 DefaultInitializationFlag(VariableMode mode)118 static InitializationFlag DefaultInitializationFlag(VariableMode mode) { 119 DCHECK(IsDeclaredVariableMode(mode)); 120 return mode == VAR ? kCreatedInitialized : kNeedsInitialization; 121 } 122 123 typedef ThreadedList<Variable> List; 124 125 private: 126 Scope* scope_; 127 const AstRawString* name_; 128 129 // If this field is set, this variable references the stored locally bound 130 // variable, but it might be shadowed by variable bindings introduced by 131 // sloppy 'eval' calls between the reference scope (inclusive) and the 132 // binding scope (exclusive). 133 Variable* local_if_not_shadowed_; 134 Variable* next_; 135 int index_; 136 int initializer_position_; 137 uint16_t bit_field_; 138 139 class VariableModeField : public BitField16<VariableMode, 0, 3> {}; 140 class VariableKindField 141 : public BitField16<VariableKind, VariableModeField::kNext, 3> {}; 142 class LocationField 143 : public BitField16<VariableLocation, VariableKindField::kNext, 3> {}; 144 class ForceContextAllocationField 145 : public BitField16<bool, LocationField::kNext, 1> {}; 146 class IsUsedField 147 : public BitField16<bool, ForceContextAllocationField::kNext, 1> {}; 148 class InitializationFlagField 149 : public BitField16<InitializationFlag, IsUsedField::kNext, 2> {}; 150 class MaybeAssignedFlagField 151 : public BitField16<MaybeAssignedFlag, InitializationFlagField::kNext, 152 2> {}; next()153 Variable** next() { return &next_; } 154 friend List; 155 }; 156 } // namespace internal 157 } // namespace v8 158 159 #endif // V8_AST_VARIABLES_H_ 160