OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/debug.h" | 8 #include "src/debug.h" |
9 #include "src/scopeinfo.h" | 9 #include "src/scopeinfo.h" |
10 | 10 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 | 13 |
14 | |
15 Handle<GlobalContextTable> GlobalContextTable::Extend( | |
16 Handle<GlobalContextTable> table, Handle<Context> global_context) { | |
17 Handle<GlobalContextTable> result; | |
18 int size = table->size(); | |
rossberg
2014/11/07 13:22:38
Nit: maybe call this 'used' here for more clarity.
Dmitry Lomov (no reviews)
2014/11/07 14:29:00
Done.
| |
19 int length = table->length(); | |
20 CHECK(size >= 0 && length > 0 && size < length); | |
rossberg
2014/11/07 13:22:38
Nit: The second condition is already implied by th
Dmitry Lomov (no reviews)
2014/11/07 14:29:00
Will keep as is for clarity.
| |
21 if (size + 1 == length) { | |
22 CHECK(length < Smi::kMaxValue / 2); | |
23 result = Handle<GlobalContextTable>::cast( | |
24 FixedArray::CopySize(table, length * 2)); | |
25 } else { | |
26 result = table; | |
27 } | |
28 result->set(kSizeSlot, Smi::FromInt(size + 1)); | |
rossberg
2014/11/07 13:22:38
Introduce a set_size accessor for this.
Dmitry Lomov (no reviews)
2014/11/07 14:29:00
Done.
| |
29 | |
30 DCHECK(global_context->IsGlobalContext()); | |
31 result->set(size + 1, *global_context); | |
32 return result; | |
33 } | |
34 | |
35 | |
36 bool GlobalContextTable::Lookup(Handle<GlobalContextTable> table, | |
37 Handle<String> name, LookupResult* result) { | |
38 for (int i = 0; i < table->size(); i++) { | |
39 Handle<Context> context = GetContext(table, i); | |
40 DCHECK(context->IsGlobalContext()); | |
41 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | |
42 int slot_index = ScopeInfo::ContextSlotIndex( | |
43 scope_info, name, &result->mode, &result->init_flag, | |
44 &result->maybe_assigned_flag); | |
45 | |
46 if (slot_index >= 0) { | |
47 result->context_index = i; | |
48 result->slot_index = slot_index; | |
49 return true; | |
50 } | |
51 } | |
52 return false; | |
53 } | |
54 | |
55 | |
14 Context* Context::declaration_context() { | 56 Context* Context::declaration_context() { |
15 Context* current = this; | 57 Context* current = this; |
16 while (!current->IsFunctionContext() && !current->IsNativeContext()) { | 58 while (!current->IsFunctionContext() && !current->IsNativeContext()) { |
17 current = current->previous(); | 59 current = current->previous(); |
18 DCHECK(current->closure() == closure()); | 60 DCHECK(current->closure() == closure()); |
19 } | 61 } |
20 return current; | 62 return current; |
21 } | 63 } |
22 | 64 |
23 | 65 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 Maybe<bool> blacklist = JSReceiver::HasProperty( | 137 Maybe<bool> blacklist = JSReceiver::HasProperty( |
96 Handle<JSReceiver>::cast(unscopables), it->name()); | 138 Handle<JSReceiver>::cast(unscopables), it->name()); |
97 if (!blacklist.has_value) { | 139 if (!blacklist.has_value) { |
98 DCHECK(isolate->has_pending_exception()); | 140 DCHECK(isolate->has_pending_exception()); |
99 return Maybe<PropertyAttributes>(); | 141 return Maybe<PropertyAttributes>(); |
100 } | 142 } |
101 if (blacklist.value) return maybe(ABSENT); | 143 if (blacklist.value) return maybe(ABSENT); |
102 return attrs; | 144 return attrs; |
103 } | 145 } |
104 | 146 |
147 static void GetAttributesAndBindingFlags(VariableMode mode, | |
148 InitializationFlag init_flag, | |
149 PropertyAttributes* attributes, | |
150 BindingFlags* binding_flags) { | |
151 switch (mode) { | |
152 case INTERNAL: // Fall through. | |
153 case VAR: | |
154 *attributes = NONE; | |
155 *binding_flags = MUTABLE_IS_INITIALIZED; | |
156 break; | |
157 case LET: | |
158 *attributes = NONE; | |
159 *binding_flags = (init_flag == kNeedsInitialization) | |
160 ? MUTABLE_CHECK_INITIALIZED | |
161 : MUTABLE_IS_INITIALIZED; | |
162 break; | |
163 case CONST_LEGACY: | |
164 *attributes = READ_ONLY; | |
165 *binding_flags = (init_flag == kNeedsInitialization) | |
166 ? IMMUTABLE_CHECK_INITIALIZED | |
167 : IMMUTABLE_IS_INITIALIZED; | |
168 break; | |
169 case CONST: | |
170 *attributes = READ_ONLY; | |
171 *binding_flags = (init_flag == kNeedsInitialization) | |
172 ? IMMUTABLE_CHECK_INITIALIZED_HARMONY | |
173 : IMMUTABLE_IS_INITIALIZED_HARMONY; | |
174 break; | |
175 case MODULE: | |
176 *attributes = READ_ONLY; | |
177 *binding_flags = IMMUTABLE_IS_INITIALIZED_HARMONY; | |
178 break; | |
179 case DYNAMIC: | |
180 case DYNAMIC_GLOBAL: | |
181 case DYNAMIC_LOCAL: | |
182 case TEMPORARY: | |
183 // Note: Fixed context slots are statically allocated by the compiler. | |
184 // Statically allocated variables always have a statically known mode, | |
185 // which is the mode with which they were declared when added to the | |
186 // scope. Thus, the DYNAMIC mode (which corresponds to dynamically | |
187 // declared variables that were introduced through declaration nodes) | |
188 // must not appear here. | |
189 UNREACHABLE(); | |
190 break; | |
191 } | |
192 } | |
193 | |
105 | 194 |
106 Handle<Object> Context::Lookup(Handle<String> name, | 195 Handle<Object> Context::Lookup(Handle<String> name, |
107 ContextLookupFlags flags, | 196 ContextLookupFlags flags, |
108 int* index, | 197 int* index, |
109 PropertyAttributes* attributes, | 198 PropertyAttributes* attributes, |
110 BindingFlags* binding_flags) { | 199 BindingFlags* binding_flags) { |
111 Isolate* isolate = GetIsolate(); | 200 Isolate* isolate = GetIsolate(); |
112 Handle<Context> context(this, isolate); | 201 Handle<Context> context(this, isolate); |
113 | 202 |
114 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0; | 203 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0; |
115 *index = -1; | 204 *index = -1; |
116 *attributes = ABSENT; | 205 *attributes = ABSENT; |
117 *binding_flags = MISSING_BINDING; | 206 *binding_flags = MISSING_BINDING; |
118 | 207 |
119 if (FLAG_trace_contexts) { | 208 if (FLAG_trace_contexts) { |
120 PrintF("Context::Lookup("); | 209 PrintF("Context::Lookup("); |
121 name->ShortPrint(); | 210 name->ShortPrint(); |
122 PrintF(")\n"); | 211 PrintF(")\n"); |
123 } | 212 } |
124 | 213 |
125 bool visited_global_context = false; | |
126 | |
127 do { | 214 do { |
128 if (FLAG_trace_contexts) { | 215 if (FLAG_trace_contexts) { |
129 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); | 216 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); |
130 if (context->IsGlobalContext()) PrintF(" (global context)"); | 217 if (context->IsGlobalContext()) PrintF(" (global context)"); |
131 if (context->IsNativeContext()) PrintF(" (native context)"); | 218 if (context->IsNativeContext()) PrintF(" (native context)"); |
132 PrintF("\n"); | 219 PrintF("\n"); |
133 } | 220 } |
134 | 221 |
135 if (follow_context_chain && FLAG_harmony_scoping && | |
136 !visited_global_context && | |
137 (context->IsGlobalContext() || context->IsNativeContext())) { | |
138 // For lexical scoping, on a top level, we might resolve to the | |
139 // lexical bindings introduced by later scrips. Therefore we need to | |
140 // switch to the the last added global context during lookup here. | |
141 context = Handle<Context>(context->global_object()->global_context()); | |
142 visited_global_context = true; | |
143 if (FLAG_trace_contexts) { | |
144 PrintF(" - switching to current global context %p\n", | |
145 reinterpret_cast<void*>(*context)); | |
146 } | |
147 } | |
148 | 222 |
149 // 1. Check global objects, subjects of with, and extension objects. | 223 // 1. Check global objects, subjects of with, and extension objects. |
150 if (context->IsNativeContext() || | 224 if (context->IsNativeContext() || |
151 context->IsWithContext() || | 225 context->IsWithContext() || |
152 (context->IsFunctionContext() && context->has_extension())) { | 226 (context->IsFunctionContext() && context->has_extension())) { |
153 Handle<JSReceiver> object( | 227 Handle<JSReceiver> object( |
154 JSReceiver::cast(context->extension()), isolate); | 228 JSReceiver::cast(context->extension()), isolate); |
229 | |
230 if (context->IsNativeContext()) { | |
231 if (FLAG_trace_contexts) { | |
232 PrintF(" - trying other global contexts\n"); | |
233 } | |
234 // Try other global contexts. | |
235 Handle<GlobalContextTable> global_contexts( | |
236 context->global_object()->native_context()->global_context_table()); | |
237 GlobalContextTable::LookupResult r; | |
238 if (GlobalContextTable::Lookup(global_contexts, name, &r)) { | |
239 if (FLAG_trace_contexts) { | |
240 Handle<Context> c = GlobalContextTable::GetContext(global_contexts, | |
241 r.context_index); | |
242 PrintF("=> found property in global context %d: %p\n", | |
243 r.context_index, reinterpret_cast<void*>(*c)); | |
244 } | |
245 *index = r.slot_index; | |
246 GetAttributesAndBindingFlags(r.mode, r.init_flag, attributes, | |
247 binding_flags); | |
248 return GlobalContextTable::GetContext(global_contexts, | |
249 r.context_index); | |
250 } | |
251 } | |
252 | |
155 // Context extension objects needs to behave as if they have no | 253 // Context extension objects needs to behave as if they have no |
156 // prototype. So even if we want to follow prototype chains, we need | 254 // prototype. So even if we want to follow prototype chains, we need |
157 // to only do a local lookup for context extension objects. | 255 // to only do a local lookup for context extension objects. |
158 Maybe<PropertyAttributes> maybe; | 256 Maybe<PropertyAttributes> maybe; |
159 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 || | 257 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 || |
160 object->IsJSContextExtensionObject()) { | 258 object->IsJSContextExtensionObject()) { |
161 maybe = JSReceiver::GetOwnPropertyAttributes(object, name); | 259 maybe = JSReceiver::GetOwnPropertyAttributes(object, name); |
162 } else if (context->IsWithContext()) { | 260 } else if (context->IsWithContext()) { |
163 LookupIterator it(object, name); | 261 LookupIterator it(object, name); |
164 maybe = UnscopableLookup(&it); | 262 maybe = UnscopableLookup(&it); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 MaybeAssignedFlag maybe_assigned_flag; | 297 MaybeAssignedFlag maybe_assigned_flag; |
200 int slot_index = ScopeInfo::ContextSlotIndex( | 298 int slot_index = ScopeInfo::ContextSlotIndex( |
201 scope_info, name, &mode, &init_flag, &maybe_assigned_flag); | 299 scope_info, name, &mode, &init_flag, &maybe_assigned_flag); |
202 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS); | 300 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS); |
203 if (slot_index >= 0) { | 301 if (slot_index >= 0) { |
204 if (FLAG_trace_contexts) { | 302 if (FLAG_trace_contexts) { |
205 PrintF("=> found local in context slot %d (mode = %d)\n", | 303 PrintF("=> found local in context slot %d (mode = %d)\n", |
206 slot_index, mode); | 304 slot_index, mode); |
207 } | 305 } |
208 *index = slot_index; | 306 *index = slot_index; |
209 // Note: Fixed context slots are statically allocated by the compiler. | 307 GetAttributesAndBindingFlags(mode, init_flag, attributes, |
210 // Statically allocated variables always have a statically known mode, | 308 binding_flags); |
211 // which is the mode with which they were declared when added to the | |
212 // scope. Thus, the DYNAMIC mode (which corresponds to dynamically | |
213 // declared variables that were introduced through declaration nodes) | |
214 // must not appear here. | |
215 switch (mode) { | |
216 case INTERNAL: // Fall through. | |
217 case VAR: | |
218 *attributes = NONE; | |
219 *binding_flags = MUTABLE_IS_INITIALIZED; | |
220 break; | |
221 case LET: | |
222 *attributes = NONE; | |
223 *binding_flags = (init_flag == kNeedsInitialization) | |
224 ? MUTABLE_CHECK_INITIALIZED : MUTABLE_IS_INITIALIZED; | |
225 break; | |
226 case CONST_LEGACY: | |
227 *attributes = READ_ONLY; | |
228 *binding_flags = (init_flag == kNeedsInitialization) | |
229 ? IMMUTABLE_CHECK_INITIALIZED : IMMUTABLE_IS_INITIALIZED; | |
230 break; | |
231 case CONST: | |
232 *attributes = READ_ONLY; | |
233 *binding_flags = (init_flag == kNeedsInitialization) | |
234 ? IMMUTABLE_CHECK_INITIALIZED_HARMONY : | |
235 IMMUTABLE_IS_INITIALIZED_HARMONY; | |
236 break; | |
237 case MODULE: | |
238 *attributes = READ_ONLY; | |
239 *binding_flags = IMMUTABLE_IS_INITIALIZED_HARMONY; | |
240 break; | |
241 case DYNAMIC: | |
242 case DYNAMIC_GLOBAL: | |
243 case DYNAMIC_LOCAL: | |
244 case TEMPORARY: | |
245 UNREACHABLE(); | |
246 break; | |
247 } | |
248 return context; | 309 return context; |
249 } | 310 } |
250 | 311 |
251 // Check the slot corresponding to the intermediate context holding | 312 // Check the slot corresponding to the intermediate context holding |
252 // only the function name variable. | 313 // only the function name variable. |
253 if (follow_context_chain && context->IsFunctionContext()) { | 314 if (follow_context_chain && context->IsFunctionContext()) { |
254 VariableMode mode; | 315 VariableMode mode; |
255 int function_index = scope_info->FunctionContextSlotIndex(*name, &mode); | 316 int function_index = scope_info->FunctionContextSlotIndex(*name, &mode); |
256 if (function_index >= 0) { | 317 if (function_index >= 0) { |
257 if (FLAG_trace_contexts) { | 318 if (FLAG_trace_contexts) { |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
427 bool Context::IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object) { | 488 bool Context::IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object) { |
428 // During bootstrapping we allow all objects to pass as global | 489 // During bootstrapping we allow all objects to pass as global |
429 // objects. This is necessary to fix circular dependencies. | 490 // objects. This is necessary to fix circular dependencies. |
430 return isolate->heap()->gc_state() != Heap::NOT_IN_GC || | 491 return isolate->heap()->gc_state() != Heap::NOT_IN_GC || |
431 isolate->bootstrapper()->IsActive() || | 492 isolate->bootstrapper()->IsActive() || |
432 object->IsGlobalObject(); | 493 object->IsGlobalObject(); |
433 } | 494 } |
434 #endif | 495 #endif |
435 | 496 |
436 } } // namespace v8::internal | 497 } } // namespace v8::internal |
OLD | NEW |