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

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: Rebased patch for landing 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
« no previous file with comments | « src/contexts.h ('k') | src/factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 Handle<GlobalContextTable> result;
18 int used = table->used();
19 int length = table->length();
20 CHECK(used >= 0 && length > 0 && used < length);
21 if (used + 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_used(used + 1);
29
30 DCHECK(global_context->IsGlobalContext());
31 result->set(used + 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->used(); 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
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
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
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
OLDNEW
« no previous file with comments | « src/contexts.h ('k') | src/factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698