Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(75)

Side by Side Diff: src/contexts.cc

Issue 705663004: harmony_scoping: Implement lexical bindings at top level (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 Isolate* isolate = global_context->GetIsolate();
18 Handle<GlobalContextTable> result;
19 if (table.is_null()) {
20 result = isolate->factory()->NewGlobalContextTable(1);
21 } else {
22 int length = table->length();
23 result = Handle<GlobalContextTable>::cast(
24 FixedArray::CopySize(table, length + 1));
rossberg 2014/11/06 12:29:12 This should perhaps double the table size, pre-all
Dmitry Lomov (no reviews) 2014/11/06 17:26:58 Done.
25 }
26 DCHECK(global_context->IsGlobalContext());
27 result->set(result->size() - 1, *global_context);
28 return result;
29 }
30
31
32 bool GlobalContextTable::Lookup(Handle<GlobalContextTable> table,
33 Handle<String> name, LookupResult* result) {
34 for (int i = 0; i < table->size(); i++) {
35 Handle<Context> context = GetContext(table, i);
36 DCHECK(context->IsGlobalContext());
37 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
38 int slot_index = ScopeInfo::ContextSlotIndex(
39 scope_info, name, &result->mode_, &result->init_flag_,
40 &result->maybe_assigned_flag_);
41
42 if (slot_index >= 0) {
43 result->context_index_ = i;
44 result->slot_index_ = slot_index;
45 return true;
46 }
47 }
48 return false;
49 }
50
51
14 Context* Context::declaration_context() { 52 Context* Context::declaration_context() {
15 Context* current = this; 53 Context* current = this;
16 while (!current->IsFunctionContext() && !current->IsNativeContext()) { 54 while (!current->IsFunctionContext() && !current->IsNativeContext()) {
17 current = current->previous(); 55 current = current->previous();
18 DCHECK(current->closure() == closure()); 56 DCHECK(current->closure() == closure());
19 } 57 }
20 return current; 58 return current;
21 } 59 }
22 60
23 61
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 Maybe<bool> blacklist = JSReceiver::HasProperty( 133 Maybe<bool> blacklist = JSReceiver::HasProperty(
96 Handle<JSReceiver>::cast(unscopables), it->name()); 134 Handle<JSReceiver>::cast(unscopables), it->name());
97 if (!blacklist.has_value) { 135 if (!blacklist.has_value) {
98 DCHECK(isolate->has_pending_exception()); 136 DCHECK(isolate->has_pending_exception());
99 return Maybe<PropertyAttributes>(); 137 return Maybe<PropertyAttributes>();
100 } 138 }
101 if (blacklist.value) return maybe(ABSENT); 139 if (blacklist.value) return maybe(ABSENT);
102 return attrs; 140 return attrs;
103 } 141 }
104 142
143 static void GetAttributesAndBindingFlags(VariableMode mode,
144 InitializationFlag init_flag,
145 PropertyAttributes* attributes,
146 BindingFlags* binding_flags) {
147 // Note: Fixed context slots are statically allocated by the compiler.
rossberg 2014/11/06 12:29:12 Nit: why not move this comment next to the UNREACH
148 // Statically allocated variables always have a statically known mode,
149 // which is the mode with which they were declared when added to the
150 // scope. Thus, the DYNAMIC mode (which corresponds to dynamically
151 // declared variables that were introduced through declaration nodes)
152 // must not appear here.
153 switch (mode) {
154 case INTERNAL: // Fall through.
155 case VAR:
156 *attributes = NONE;
157 *binding_flags = MUTABLE_IS_INITIALIZED;
158 break;
159 case LET:
160 *attributes = NONE;
161 *binding_flags = (init_flag == kNeedsInitialization)
162 ? MUTABLE_CHECK_INITIALIZED
163 : MUTABLE_IS_INITIALIZED;
164 break;
165 case CONST_LEGACY:
166 *attributes = READ_ONLY;
167 *binding_flags = (init_flag == kNeedsInitialization)
168 ? IMMUTABLE_CHECK_INITIALIZED
169 : IMMUTABLE_IS_INITIALIZED;
170 break;
171 case CONST:
172 *attributes = READ_ONLY;
173 *binding_flags = (init_flag == kNeedsInitialization)
174 ? IMMUTABLE_CHECK_INITIALIZED_HARMONY
175 : IMMUTABLE_IS_INITIALIZED_HARMONY;
176 break;
177 case MODULE:
178 *attributes = READ_ONLY;
179 *binding_flags = IMMUTABLE_IS_INITIALIZED_HARMONY;
180 break;
181 case DYNAMIC:
182 case DYNAMIC_GLOBAL:
183 case DYNAMIC_LOCAL:
184 case TEMPORARY:
185 UNREACHABLE();
186 break;
187 }
188 }
189
105 190
106 Handle<Object> Context::Lookup(Handle<String> name, 191 Handle<Object> Context::Lookup(Handle<String> name,
107 ContextLookupFlags flags, 192 ContextLookupFlags flags,
108 int* index, 193 int* index,
109 PropertyAttributes* attributes, 194 PropertyAttributes* attributes,
110 BindingFlags* binding_flags) { 195 BindingFlags* binding_flags) {
111 Isolate* isolate = GetIsolate(); 196 Isolate* isolate = GetIsolate();
112 Handle<Context> context(this, isolate); 197 Handle<Context> context(this, isolate);
113 198
114 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0; 199 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
115 *index = -1; 200 *index = -1;
116 *attributes = ABSENT; 201 *attributes = ABSENT;
117 *binding_flags = MISSING_BINDING; 202 *binding_flags = MISSING_BINDING;
118 203
119 if (FLAG_trace_contexts) { 204 if (FLAG_trace_contexts) {
120 PrintF("Context::Lookup("); 205 PrintF("Context::Lookup(");
121 name->ShortPrint(); 206 name->ShortPrint();
122 PrintF(")\n"); 207 PrintF(")\n");
123 } 208 }
124 209
125 bool visited_global_context = false;
126
127 do { 210 do {
128 if (FLAG_trace_contexts) { 211 if (FLAG_trace_contexts) {
129 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); 212 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
130 if (context->IsGlobalContext()) PrintF(" (global context)"); 213 if (context->IsGlobalContext()) PrintF(" (global context)");
131 if (context->IsNativeContext()) PrintF(" (native context)"); 214 if (context->IsNativeContext()) PrintF(" (native context)");
132 PrintF("\n"); 215 PrintF("\n");
133 } 216 }
134 217
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 218
149 // 1. Check global objects, subjects of with, and extension objects. 219 // 1. Check global objects, subjects of with, and extension objects.
150 if (context->IsNativeContext() || 220 if (context->IsNativeContext() ||
151 context->IsWithContext() || 221 context->IsWithContext() ||
152 (context->IsFunctionContext() && context->has_extension())) { 222 (context->IsFunctionContext() && context->has_extension())) {
153 Handle<JSReceiver> object( 223 Handle<JSReceiver> object(
154 JSReceiver::cast(context->extension()), isolate); 224 JSReceiver::cast(context->extension()), isolate);
225
226 if (context->IsNativeContext()) {
227 if (FLAG_trace_contexts) {
228 PrintF(" - trying other global contexts\n");
229 }
230 // Try other global contexts.
231 Handle<GlobalContextTable> global_contexts(
232 context->global_object()->native_context()->global_context_table());
233 GlobalContextTable::LookupResult r;
234 if (GlobalContextTable::Lookup(global_contexts, name, &r)) {
235 if (FLAG_trace_contexts) {
236 Handle<Context> c = GlobalContextTable::GetContext(
237 global_contexts, r.context_index_);
238 PrintF("=> found property in global context %d: %p\n",
239 r.context_index_, reinterpret_cast<void*>(*c));
240 }
241 *index = r.slot_index_;
242 GetAttributesAndBindingFlags(r.mode_, r.init_flag_, attributes,
243 binding_flags);
244 return GlobalContextTable::GetContext(global_contexts,
245 r.context_index_);
246 }
247 }
248
155 // Context extension objects needs to behave as if they have no 249 // Context extension objects needs to behave as if they have no
156 // prototype. So even if we want to follow prototype chains, we need 250 // prototype. So even if we want to follow prototype chains, we need
157 // to only do a local lookup for context extension objects. 251 // to only do a local lookup for context extension objects.
158 Maybe<PropertyAttributes> maybe; 252 Maybe<PropertyAttributes> maybe;
159 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 || 253 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
160 object->IsJSContextExtensionObject()) { 254 object->IsJSContextExtensionObject()) {
161 maybe = JSReceiver::GetOwnPropertyAttributes(object, name); 255 maybe = JSReceiver::GetOwnPropertyAttributes(object, name);
162 } else if (context->IsWithContext()) { 256 } else if (context->IsWithContext()) {
163 LookupIterator it(object, name); 257 LookupIterator it(object, name);
164 maybe = UnscopableLookup(&it); 258 maybe = UnscopableLookup(&it);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 MaybeAssignedFlag maybe_assigned_flag; 293 MaybeAssignedFlag maybe_assigned_flag;
200 int slot_index = ScopeInfo::ContextSlotIndex( 294 int slot_index = ScopeInfo::ContextSlotIndex(
201 scope_info, name, &mode, &init_flag, &maybe_assigned_flag); 295 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
202 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS); 296 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
203 if (slot_index >= 0) { 297 if (slot_index >= 0) {
204 if (FLAG_trace_contexts) { 298 if (FLAG_trace_contexts) {
205 PrintF("=> found local in context slot %d (mode = %d)\n", 299 PrintF("=> found local in context slot %d (mode = %d)\n",
206 slot_index, mode); 300 slot_index, mode);
207 } 301 }
208 *index = slot_index; 302 *index = slot_index;
209 // Note: Fixed context slots are statically allocated by the compiler. 303 GetAttributesAndBindingFlags(mode, init_flag, attributes,
210 // Statically allocated variables always have a statically known mode, 304 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; 305 return context;
249 } 306 }
250 307
251 // Check the slot corresponding to the intermediate context holding 308 // Check the slot corresponding to the intermediate context holding
252 // only the function name variable. 309 // only the function name variable.
253 if (follow_context_chain && context->IsFunctionContext()) { 310 if (follow_context_chain && context->IsFunctionContext()) {
254 VariableMode mode; 311 VariableMode mode;
255 int function_index = scope_info->FunctionContextSlotIndex(*name, &mode); 312 int function_index = scope_info->FunctionContextSlotIndex(*name, &mode);
256 if (function_index >= 0) { 313 if (function_index >= 0) {
257 if (FLAG_trace_contexts) { 314 if (FLAG_trace_contexts) {
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 bool Context::IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object) { 484 bool Context::IsBootstrappingOrGlobalObject(Isolate* isolate, Object* object) {
428 // During bootstrapping we allow all objects to pass as global 485 // During bootstrapping we allow all objects to pass as global
429 // objects. This is necessary to fix circular dependencies. 486 // objects. This is necessary to fix circular dependencies.
430 return isolate->heap()->gc_state() != Heap::NOT_IN_GC || 487 return isolate->heap()->gc_state() != Heap::NOT_IN_GC ||
431 isolate->bootstrapper()->IsActive() || 488 isolate->bootstrapper()->IsActive() ||
432 object->IsGlobalObject(); 489 object->IsGlobalObject();
433 } 490 }
434 #endif 491 #endif
435 492
436 } } // namespace v8::internal 493 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698