blob: 7549d205182731b525d69674db7bed8e0e3cdd31 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/contexts.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00007#include "src/ast/scopeinfo.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#include "src/bootstrapper.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/debug/debug.h"
10#include "src/isolate-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000011
12namespace v8 {
13namespace internal {
14
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015
16Handle<ScriptContextTable> ScriptContextTable::Extend(
17 Handle<ScriptContextTable> table, Handle<Context> script_context) {
18 Handle<ScriptContextTable> result;
19 int used = table->used();
20 int length = table->length();
21 CHECK(used >= 0 && length > 0 && used < length);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022 if (used + kFirstContextSlot == length) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023 CHECK(length < Smi::kMaxValue / 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024 Isolate* isolate = table->GetIsolate();
25 Handle<FixedArray> copy =
26 isolate->factory()->CopyFixedArrayAndGrow(table, length);
27 copy->set_map(isolate->heap()->script_context_table_map());
28 result = Handle<ScriptContextTable>::cast(copy);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040029 } else {
30 result = table;
31 }
32 result->set_used(used + 1);
33
34 DCHECK(script_context->IsScriptContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035 result->set(used + kFirstContextSlot, *script_context);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040036 return result;
37}
38
39
40bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table,
41 Handle<String> name, LookupResult* result) {
42 for (int i = 0; i < table->used(); i++) {
43 Handle<Context> context = GetContext(table, i);
44 DCHECK(context->IsScriptContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000045 Handle<ScopeInfo> scope_info(context->scope_info());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040046 int slot_index = ScopeInfo::ContextSlotIndex(
47 scope_info, name, &result->mode, &result->init_flag,
48 &result->maybe_assigned_flag);
49
50 if (slot_index >= 0) {
51 result->context_index = i;
52 result->slot_index = slot_index;
53 return true;
54 }
55 }
56 return false;
57}
58
59
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060bool Context::is_declaration_context() {
61 if (IsFunctionContext() || IsNativeContext() || IsScriptContext()) {
62 return true;
63 }
64 if (!IsBlockContext()) return false;
65 Object* ext = extension();
66 // If we have the special extension, we immediately know it must be a
67 // declaration scope. That's just a small performance shortcut.
68 return ext->IsSloppyBlockWithEvalContextExtension()
69 || ScopeInfo::cast(ext)->is_declaration_scope();
70}
71
72
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000073Context* Context::declaration_context() {
74 Context* current = this;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 while (!current->is_declaration_context()) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000076 current = current->previous();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000077 DCHECK(current->closure() == closure());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000078 }
79 return current;
80}
81
Ben Murdoch097c5b22016-05-18 11:27:45 +010082Context* Context::closure_context() {
83 Context* current = this;
84 while (!current->IsFunctionContext() && !current->IsScriptContext() &&
85 !current->IsNativeContext()) {
86 current = current->previous();
87 DCHECK(current->closure() == closure());
88 }
89 return current;
90}
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000091
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092JSObject* Context::extension_object() {
93 DCHECK(IsNativeContext() || IsFunctionContext() || IsBlockContext());
94 HeapObject* object = extension();
95 if (object->IsTheHole()) return nullptr;
96 if (IsBlockContext()) {
97 if (!object->IsSloppyBlockWithEvalContextExtension()) return nullptr;
98 object = SloppyBlockWithEvalContextExtension::cast(object)->extension();
Steve Blocka7e24c12009-10-30 11:49:00 +000099 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100 DCHECK(object->IsJSContextExtensionObject() ||
101 (IsNativeContext() && object->IsJSGlobalObject()));
102 return JSObject::cast(object);
103}
104
105
106JSReceiver* Context::extension_receiver() {
107 DCHECK(IsNativeContext() || IsWithContext() ||
108 IsFunctionContext() || IsBlockContext());
109 return IsWithContext() ? JSReceiver::cast(extension()) : extension_object();
110}
111
112
113ScopeInfo* Context::scope_info() {
114 DCHECK(IsModuleContext() || IsScriptContext() || IsBlockContext());
115 HeapObject* object = extension();
116 if (object->IsSloppyBlockWithEvalContextExtension()) {
117 DCHECK(IsBlockContext());
118 object = SloppyBlockWithEvalContextExtension::cast(object)->scope_info();
119 }
120 return ScopeInfo::cast(object);
121}
122
123
124String* Context::catch_name() {
125 DCHECK(IsCatchContext());
126 return String::cast(extension());
127}
128
129
130JSGlobalObject* Context::global_object() {
131 return JSGlobalObject::cast(native_context()->extension());
Steve Blocka7e24c12009-10-30 11:49:00 +0000132}
133
134
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400135Context* Context::script_context() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 Context* current = this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137 while (!current->IsScriptContext()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 current = current->previous();
139 }
140 return current;
141}
142
143
Steve Blocka7e24c12009-10-30 11:49:00 +0000144JSObject* Context::global_proxy() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 return native_context()->global_proxy_object();
Steve Blocka7e24c12009-10-30 11:49:00 +0000146}
147
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148
Steve Blocka7e24c12009-10-30 11:49:00 +0000149void Context::set_global_proxy(JSObject* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 native_context()->set_global_proxy_object(object);
151}
152
153
154/**
155 * Lookups a property in an object environment, taking the unscopables into
156 * account. This is used For HasBinding spec algorithms for ObjectEnvironment.
157 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158static Maybe<bool> UnscopableLookup(LookupIterator* it) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000159 Isolate* isolate = it->isolate();
160
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 Maybe<bool> found = JSReceiver::HasProperty(it);
162 if (!found.IsJust() || !found.FromJust()) return found;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 Handle<Object> unscopables;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
166 isolate, unscopables,
167 Object::GetProperty(it->GetReceiver(),
168 isolate->factory()->unscopables_symbol()),
169 Nothing<bool>());
170 if (!unscopables->IsJSReceiver()) return Just(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400171 Handle<Object> blacklist;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, blacklist,
173 Object::GetProperty(unscopables, it->name()),
174 Nothing<bool>());
175 return Just(!blacklist->BooleanValue());
Steve Blocka7e24c12009-10-30 11:49:00 +0000176}
177
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178static void GetAttributesAndBindingFlags(VariableMode mode,
179 InitializationFlag init_flag,
180 PropertyAttributes* attributes,
181 BindingFlags* binding_flags) {
182 switch (mode) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400183 case VAR:
184 *attributes = NONE;
185 *binding_flags = MUTABLE_IS_INITIALIZED;
186 break;
187 case LET:
188 *attributes = NONE;
189 *binding_flags = (init_flag == kNeedsInitialization)
190 ? MUTABLE_CHECK_INITIALIZED
191 : MUTABLE_IS_INITIALIZED;
192 break;
193 case CONST_LEGACY:
194 *attributes = READ_ONLY;
195 *binding_flags = (init_flag == kNeedsInitialization)
196 ? IMMUTABLE_CHECK_INITIALIZED
197 : IMMUTABLE_IS_INITIALIZED;
198 break;
199 case CONST:
200 *attributes = READ_ONLY;
201 *binding_flags = (init_flag == kNeedsInitialization)
202 ? IMMUTABLE_CHECK_INITIALIZED_HARMONY
203 : IMMUTABLE_IS_INITIALIZED_HARMONY;
204 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 case IMPORT:
206 // TODO(ES6)
207 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208 break;
209 case DYNAMIC:
210 case DYNAMIC_GLOBAL:
211 case DYNAMIC_LOCAL:
212 case TEMPORARY:
213 // Note: Fixed context slots are statically allocated by the compiler.
214 // Statically allocated variables always have a statically known mode,
215 // which is the mode with which they were declared when added to the
216 // scope. Thus, the DYNAMIC mode (which corresponds to dynamically
217 // declared variables that were introduced through declaration nodes)
218 // must not appear here.
219 UNREACHABLE();
220 break;
221 }
222}
223
Steve Blocka7e24c12009-10-30 11:49:00 +0000224
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000225Handle<Object> Context::Lookup(Handle<String> name,
226 ContextLookupFlags flags,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100227 int* index,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000228 PropertyAttributes* attributes,
229 BindingFlags* binding_flags) {
Steve Block44f0eee2011-05-26 01:26:41 +0100230 Isolate* isolate = GetIsolate();
231 Handle<Context> context(this, isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232
233 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 *index = kNotFound;
Steve Blocka7e24c12009-10-30 11:49:00 +0000235 *attributes = ABSENT;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000236 *binding_flags = MISSING_BINDING;
Steve Blocka7e24c12009-10-30 11:49:00 +0000237
238 if (FLAG_trace_contexts) {
239 PrintF("Context::Lookup(");
240 name->ShortPrint();
241 PrintF(")\n");
242 }
243
244 do {
245 if (FLAG_trace_contexts) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100246 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400247 if (context->IsScriptContext()) PrintF(" (script context)");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000248 if (context->IsNativeContext()) PrintF(" (native context)");
Steve Blocka7e24c12009-10-30 11:49:00 +0000249 PrintF("\n");
250 }
251
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100252 // 1. Check global objects, subjects of with, and extension objects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 if ((context->IsNativeContext() ||
254 (context->IsWithContext() && ((flags & SKIP_WITH_CONTEXT) == 0)) ||
255 context->IsFunctionContext() || context->IsBlockContext()) &&
256 context->extension_receiver() != nullptr) {
257 Handle<JSReceiver> object(context->extension_receiver());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400258
259 if (context->IsNativeContext()) {
260 if (FLAG_trace_contexts) {
261 PrintF(" - trying other script contexts\n");
262 }
263 // Try other script contexts.
264 Handle<ScriptContextTable> script_contexts(
265 context->global_object()->native_context()->script_context_table());
266 ScriptContextTable::LookupResult r;
267 if (ScriptContextTable::Lookup(script_contexts, name, &r)) {
268 if (FLAG_trace_contexts) {
269 Handle<Context> c = ScriptContextTable::GetContext(script_contexts,
270 r.context_index);
271 PrintF("=> found property in script context %d: %p\n",
272 r.context_index, reinterpret_cast<void*>(*c));
273 }
274 *index = r.slot_index;
275 GetAttributesAndBindingFlags(r.mode, r.init_flag, attributes,
276 binding_flags);
277 return ScriptContextTable::GetContext(script_contexts,
278 r.context_index);
279 }
280 }
281
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100282 // Context extension objects needs to behave as if they have no
283 // prototype. So even if we want to follow prototype chains, we need
284 // to only do a local lookup for context extension objects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 Maybe<PropertyAttributes> maybe = Nothing<PropertyAttributes>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100286 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
287 object->IsJSContextExtensionObject()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288 maybe = JSReceiver::GetOwnPropertyAttributes(object, name);
289 } else if (context->IsWithContext()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 // A with context will never bind "this".
291 if (name->Equals(*isolate->factory()->this_string())) {
292 maybe = Just(ABSENT);
293 } else {
294 LookupIterator it(object, name);
295 Maybe<bool> found = UnscopableLookup(&it);
296 if (found.IsNothing()) {
297 maybe = Nothing<PropertyAttributes>();
298 } else {
299 // Luckily, consumers of |maybe| only care whether the property
300 // was absent or not, so we can return a dummy |NONE| value
301 // for its attributes when it was present.
302 maybe = Just(found.FromJust() ? NONE : ABSENT);
303 }
304 }
Ben Murdoch85b71792012-04-11 18:30:58 +0100305 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 maybe = JSReceiver::GetPropertyAttributes(object, name);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100307 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 if (!maybe.IsJust()) return Handle<Object>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000310 DCHECK(!isolate->has_pending_exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 *attributes = maybe.FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 if (maybe.FromJust() != ABSENT) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100314 if (FLAG_trace_contexts) {
315 PrintF("=> found property in context object %p\n",
316 reinterpret_cast<void*>(*object));
Ben Murdoch85b71792012-04-11 18:30:58 +0100317 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100318 return object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000319 }
320 }
321
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100322 // 2. Check the context proper if it has slots.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400323 if (context->IsFunctionContext() || context->IsBlockContext() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 context->IsScriptContext()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100325 // Use serialized scope information of functions and blocks to search
326 // for the context index.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 Handle<ScopeInfo> scope_info(context->IsFunctionContext()
328 ? context->closure()->shared()->scope_info()
329 : context->scope_info());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100330 VariableMode mode;
331 InitializationFlag init_flag;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 // TODO(sigurds) Figure out whether maybe_assigned_flag should
333 // be used to compute binding_flags.
334 MaybeAssignedFlag maybe_assigned_flag;
335 int slot_index = ScopeInfo::ContextSlotIndex(
336 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
337 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100338 if (slot_index >= 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000339 if (FLAG_trace_contexts) {
340 PrintF("=> found local in context slot %d (mode = %d)\n",
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100341 slot_index, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000342 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100343 *index = slot_index;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400344 GetAttributesAndBindingFlags(mode, init_flag, attributes,
345 binding_flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 return context;
347 }
348
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000349 // Check the slot corresponding to the intermediate context holding
350 // only the function name variable.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100351 if (follow_context_chain && context->IsFunctionContext()) {
352 VariableMode mode;
353 int function_index = scope_info->FunctionContextSlotIndex(*name, &mode);
354 if (function_index >= 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 if (FLAG_trace_contexts) {
356 PrintF("=> found intermediate function in context slot %d\n",
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100357 function_index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100359 *index = function_index;
Steve Blocka7e24c12009-10-30 11:49:00 +0000360 *attributes = READ_ONLY;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000361 DCHECK(mode == CONST_LEGACY || mode == CONST);
362 *binding_flags = (mode == CONST_LEGACY)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100363 ? IMMUTABLE_IS_INITIALIZED : IMMUTABLE_IS_INITIALIZED_HARMONY;
Steve Blocka7e24c12009-10-30 11:49:00 +0000364 return context;
365 }
366 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100367
368 } else if (context->IsCatchContext()) {
369 // Catch contexts have the variable name in the extension slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370 if (String::Equals(name, handle(context->catch_name()))) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100371 if (FLAG_trace_contexts) {
372 PrintF("=> found in catch context\n");
373 }
374 *index = Context::THROWN_OBJECT_INDEX;
375 *attributes = NONE;
376 *binding_flags = MUTABLE_IS_INITIALIZED;
377 return context;
378 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 }
380
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100381 // 3. Prepare to continue with the previous (next outermost) context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 if (context->IsNativeContext() ||
383 ((flags & STOP_AT_DECLARATION_SCOPE) != 0 &&
384 context->is_declaration_context())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000385 follow_context_chain = false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000386 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100387 context = Handle<Context>(context->previous(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 }
389 } while (follow_context_chain);
390
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 if (FLAG_trace_contexts) {
392 PrintF("=> no property/slot found\n");
393 }
394 return Handle<Object>::null();
395}
396
397
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398void Context::InitializeGlobalSlots() {
399 DCHECK(IsScriptContext());
400 DisallowHeapAllocation no_gc;
401
402 ScopeInfo* scope_info = this->scope_info();
403
404 int context_globals = scope_info->ContextGlobalCount();
405 if (context_globals > 0) {
406 PropertyCell* empty_cell = GetHeap()->empty_property_cell();
407
408 int context_locals = scope_info->ContextLocalCount();
409 int index = Context::MIN_CONTEXT_SLOTS + context_locals;
410 for (int i = 0; i < context_globals; i++) {
411 set(index++, empty_cell);
412 }
413 }
414}
415
416
Ben Murdochb0fe1622011-05-05 13:52:32 +0100417void Context::AddOptimizedFunction(JSFunction* function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000418 DCHECK(IsNativeContext());
419#ifdef ENABLE_SLOW_DCHECKS
420 if (FLAG_enable_slow_asserts) {
421 Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
422 while (!element->IsUndefined()) {
423 CHECK(element != function);
424 element = JSFunction::cast(element)->next_function_link();
425 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100426 }
427
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 // Check that the context belongs to the weak native contexts list.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100429 bool found = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000430 Object* context = GetHeap()->native_contexts_list();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100431 while (!context->IsUndefined()) {
432 if (context == this) {
433 found = true;
434 break;
435 }
436 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
437 }
438 CHECK(found);
439#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440
441 // If the function link field is already used then the function was
442 // enqueued as a code flushing candidate and we remove it now.
443 if (!function->next_function_link()->IsUndefined()) {
444 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
445 flusher->EvictCandidate(function);
446 }
447
448 DCHECK(function->next_function_link()->IsUndefined());
449
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 function->set_next_function_link(get(OPTIMIZED_FUNCTIONS_LIST),
451 UPDATE_WEAK_WRITE_BARRIER);
452 set(OPTIMIZED_FUNCTIONS_LIST, function, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100453}
454
455
456void Context::RemoveOptimizedFunction(JSFunction* function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 DCHECK(IsNativeContext());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100458 Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
459 JSFunction* prev = NULL;
460 while (!element->IsUndefined()) {
461 JSFunction* element_function = JSFunction::cast(element);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462 DCHECK(element_function->next_function_link()->IsUndefined() ||
Ben Murdochb0fe1622011-05-05 13:52:32 +0100463 element_function->next_function_link()->IsJSFunction());
464 if (element_function == function) {
465 if (prev == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 set(OPTIMIZED_FUNCTIONS_LIST, element_function->next_function_link(),
467 UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100468 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 prev->set_next_function_link(element_function->next_function_link(),
470 UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100471 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472 element_function->set_next_function_link(GetHeap()->undefined_value(),
473 UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100474 return;
475 }
476 prev = element_function;
477 element = element_function->next_function_link();
478 }
479 UNREACHABLE();
480}
481
482
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483void Context::SetOptimizedFunctionsListHead(Object* head) {
484 DCHECK(IsNativeContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 set(OPTIMIZED_FUNCTIONS_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486}
487
488
Ben Murdochb0fe1622011-05-05 13:52:32 +0100489Object* Context::OptimizedFunctionsListHead() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 DCHECK(IsNativeContext());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100491 return get(OPTIMIZED_FUNCTIONS_LIST);
492}
493
494
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495void Context::AddOptimizedCode(Code* code) {
496 DCHECK(IsNativeContext());
497 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
498 DCHECK(code->next_code_link()->IsUndefined());
499 code->set_next_code_link(get(OPTIMIZED_CODE_LIST));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 set(OPTIMIZED_CODE_LIST, code, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501}
502
503
504void Context::SetOptimizedCodeListHead(Object* head) {
505 DCHECK(IsNativeContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 set(OPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000507}
508
509
510Object* Context::OptimizedCodeListHead() {
511 DCHECK(IsNativeContext());
512 return get(OPTIMIZED_CODE_LIST);
513}
514
515
516void Context::SetDeoptimizedCodeListHead(Object* head) {
517 DCHECK(IsNativeContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 set(DEOPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519}
520
521
522Object* Context::DeoptimizedCodeListHead() {
523 DCHECK(IsNativeContext());
524 return get(DEOPTIMIZED_CODE_LIST);
525}
526
527
528Handle<Object> Context::ErrorMessageForCodeGenerationFromStrings() {
529 Isolate* isolate = GetIsolate();
530 Handle<Object> result(error_message_for_code_gen_from_strings(), isolate);
531 if (!result->IsUndefined()) return result;
532 return isolate->factory()->NewStringFromStaticChars(
533 "Code generation from strings disallowed for this context");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100534}
535
536
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537#define COMPARE_NAME(index, type, name) \
538 if (string->IsOneByteEqualTo(STATIC_CHAR_VECTOR(#name))) return index;
539
540int Context::ImportedFieldIndexForName(Handle<String> string) {
541 NATIVE_CONTEXT_IMPORTED_FIELDS(COMPARE_NAME)
542 return kNotFound;
543}
544
545
546int Context::IntrinsicIndexForName(Handle<String> string) {
547 NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(COMPARE_NAME);
548 return kNotFound;
549}
550
551#undef COMPARE_NAME
552
553
Steve Blocka7e24c12009-10-30 11:49:00 +0000554#ifdef DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555
556bool Context::IsBootstrappingOrNativeContext(Isolate* isolate, Object* object) {
557 // During bootstrapping we allow all objects to pass as global
558 // objects. This is necessary to fix circular dependencies.
559 return isolate->heap()->gc_state() != Heap::NOT_IN_GC ||
560 isolate->bootstrapper()->IsActive() || object->IsNativeContext();
561}
562
563
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564bool Context::IsBootstrappingOrValidParentContext(
565 Object* object, Context* child) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000566 // During bootstrapping we allow all objects to pass as
567 // contexts. This is necessary to fix circular dependencies.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 if (child->GetIsolate()->bootstrapper()->IsActive()) return true;
569 if (!object->IsContext()) return false;
570 Context* context = Context::cast(object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400571 return context->IsNativeContext() || context->IsScriptContext() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572 context->IsModuleContext() || !child->IsModuleContext();
Steve Blocka7e24c12009-10-30 11:49:00 +0000573}
574
Steve Blocka7e24c12009-10-30 11:49:00 +0000575#endif
576
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577
578void Context::IncrementErrorsThrown() {
579 DCHECK(IsNativeContext());
580
581 int previous_value = errors_thrown()->value();
582 set_errors_thrown(Smi::FromInt(previous_value + 1));
583}
584
585
586int Context::GetErrorsThrown() { return errors_thrown()->value(); }
587
588} // namespace internal
589} // namespace v8