blob: 79a9e926a560135266f2c6aa1124dbabb58d003e [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
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083JSObject* Context::extension_object() {
84 DCHECK(IsNativeContext() || IsFunctionContext() || IsBlockContext());
85 HeapObject* object = extension();
86 if (object->IsTheHole()) return nullptr;
87 if (IsBlockContext()) {
88 if (!object->IsSloppyBlockWithEvalContextExtension()) return nullptr;
89 object = SloppyBlockWithEvalContextExtension::cast(object)->extension();
Steve Blocka7e24c12009-10-30 11:49:00 +000090 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091 DCHECK(object->IsJSContextExtensionObject() ||
92 (IsNativeContext() && object->IsJSGlobalObject()));
93 return JSObject::cast(object);
94}
95
96
97JSReceiver* Context::extension_receiver() {
98 DCHECK(IsNativeContext() || IsWithContext() ||
99 IsFunctionContext() || IsBlockContext());
100 return IsWithContext() ? JSReceiver::cast(extension()) : extension_object();
101}
102
103
104ScopeInfo* Context::scope_info() {
105 DCHECK(IsModuleContext() || IsScriptContext() || IsBlockContext());
106 HeapObject* object = extension();
107 if (object->IsSloppyBlockWithEvalContextExtension()) {
108 DCHECK(IsBlockContext());
109 object = SloppyBlockWithEvalContextExtension::cast(object)->scope_info();
110 }
111 return ScopeInfo::cast(object);
112}
113
114
115String* Context::catch_name() {
116 DCHECK(IsCatchContext());
117 return String::cast(extension());
118}
119
120
121JSGlobalObject* Context::global_object() {
122 return JSGlobalObject::cast(native_context()->extension());
Steve Blocka7e24c12009-10-30 11:49:00 +0000123}
124
125
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126Context* Context::script_context() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 Context* current = this;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128 while (!current->IsScriptContext()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 current = current->previous();
130 }
131 return current;
132}
133
134
Steve Blocka7e24c12009-10-30 11:49:00 +0000135JSObject* Context::global_proxy() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136 return native_context()->global_proxy_object();
Steve Blocka7e24c12009-10-30 11:49:00 +0000137}
138
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139
Steve Blocka7e24c12009-10-30 11:49:00 +0000140void Context::set_global_proxy(JSObject* object) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141 native_context()->set_global_proxy_object(object);
142}
143
144
145/**
146 * Lookups a property in an object environment, taking the unscopables into
147 * account. This is used For HasBinding spec algorithms for ObjectEnvironment.
148 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149static Maybe<bool> UnscopableLookup(LookupIterator* it) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 Isolate* isolate = it->isolate();
151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 Maybe<bool> found = JSReceiver::HasProperty(it);
153 if (!found.IsJust() || !found.FromJust()) return found;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000155 Handle<Object> unscopables;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
157 isolate, unscopables,
158 Object::GetProperty(it->GetReceiver(),
159 isolate->factory()->unscopables_symbol()),
160 Nothing<bool>());
161 if (!unscopables->IsJSReceiver()) return Just(true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 Handle<Object> blacklist;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, blacklist,
164 Object::GetProperty(unscopables, it->name()),
165 Nothing<bool>());
166 return Just(!blacklist->BooleanValue());
Steve Blocka7e24c12009-10-30 11:49:00 +0000167}
168
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400169static void GetAttributesAndBindingFlags(VariableMode mode,
170 InitializationFlag init_flag,
171 PropertyAttributes* attributes,
172 BindingFlags* binding_flags) {
173 switch (mode) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400174 case VAR:
175 *attributes = NONE;
176 *binding_flags = MUTABLE_IS_INITIALIZED;
177 break;
178 case LET:
179 *attributes = NONE;
180 *binding_flags = (init_flag == kNeedsInitialization)
181 ? MUTABLE_CHECK_INITIALIZED
182 : MUTABLE_IS_INITIALIZED;
183 break;
184 case CONST_LEGACY:
185 *attributes = READ_ONLY;
186 *binding_flags = (init_flag == kNeedsInitialization)
187 ? IMMUTABLE_CHECK_INITIALIZED
188 : IMMUTABLE_IS_INITIALIZED;
189 break;
190 case CONST:
191 *attributes = READ_ONLY;
192 *binding_flags = (init_flag == kNeedsInitialization)
193 ? IMMUTABLE_CHECK_INITIALIZED_HARMONY
194 : IMMUTABLE_IS_INITIALIZED_HARMONY;
195 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 case IMPORT:
197 // TODO(ES6)
198 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 break;
200 case DYNAMIC:
201 case DYNAMIC_GLOBAL:
202 case DYNAMIC_LOCAL:
203 case TEMPORARY:
204 // Note: Fixed context slots are statically allocated by the compiler.
205 // Statically allocated variables always have a statically known mode,
206 // which is the mode with which they were declared when added to the
207 // scope. Thus, the DYNAMIC mode (which corresponds to dynamically
208 // declared variables that were introduced through declaration nodes)
209 // must not appear here.
210 UNREACHABLE();
211 break;
212 }
213}
214
Steve Blocka7e24c12009-10-30 11:49:00 +0000215
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000216Handle<Object> Context::Lookup(Handle<String> name,
217 ContextLookupFlags flags,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100218 int* index,
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000219 PropertyAttributes* attributes,
220 BindingFlags* binding_flags) {
Steve Block44f0eee2011-05-26 01:26:41 +0100221 Isolate* isolate = GetIsolate();
222 Handle<Context> context(this, isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000223
224 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 *index = kNotFound;
Steve Blocka7e24c12009-10-30 11:49:00 +0000226 *attributes = ABSENT;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000227 *binding_flags = MISSING_BINDING;
Steve Blocka7e24c12009-10-30 11:49:00 +0000228
229 if (FLAG_trace_contexts) {
230 PrintF("Context::Lookup(");
231 name->ShortPrint();
232 PrintF(")\n");
233 }
234
235 do {
236 if (FLAG_trace_contexts) {
Ben Murdochf87a2032010-10-22 12:50:53 +0100237 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400238 if (context->IsScriptContext()) PrintF(" (script context)");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 if (context->IsNativeContext()) PrintF(" (native context)");
Steve Blocka7e24c12009-10-30 11:49:00 +0000240 PrintF("\n");
241 }
242
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100243 // 1. Check global objects, subjects of with, and extension objects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 if ((context->IsNativeContext() ||
245 (context->IsWithContext() && ((flags & SKIP_WITH_CONTEXT) == 0)) ||
246 context->IsFunctionContext() || context->IsBlockContext()) &&
247 context->extension_receiver() != nullptr) {
248 Handle<JSReceiver> object(context->extension_receiver());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400249
250 if (context->IsNativeContext()) {
251 if (FLAG_trace_contexts) {
252 PrintF(" - trying other script contexts\n");
253 }
254 // Try other script contexts.
255 Handle<ScriptContextTable> script_contexts(
256 context->global_object()->native_context()->script_context_table());
257 ScriptContextTable::LookupResult r;
258 if (ScriptContextTable::Lookup(script_contexts, name, &r)) {
259 if (FLAG_trace_contexts) {
260 Handle<Context> c = ScriptContextTable::GetContext(script_contexts,
261 r.context_index);
262 PrintF("=> found property in script context %d: %p\n",
263 r.context_index, reinterpret_cast<void*>(*c));
264 }
265 *index = r.slot_index;
266 GetAttributesAndBindingFlags(r.mode, r.init_flag, attributes,
267 binding_flags);
268 return ScriptContextTable::GetContext(script_contexts,
269 r.context_index);
270 }
271 }
272
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100273 // Context extension objects needs to behave as if they have no
274 // prototype. So even if we want to follow prototype chains, we need
275 // to only do a local lookup for context extension objects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 Maybe<PropertyAttributes> maybe = Nothing<PropertyAttributes>();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100277 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
278 object->IsJSContextExtensionObject()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 maybe = JSReceiver::GetOwnPropertyAttributes(object, name);
280 } else if (context->IsWithContext()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 // A with context will never bind "this".
282 if (name->Equals(*isolate->factory()->this_string())) {
283 maybe = Just(ABSENT);
284 } else {
285 LookupIterator it(object, name);
286 Maybe<bool> found = UnscopableLookup(&it);
287 if (found.IsNothing()) {
288 maybe = Nothing<PropertyAttributes>();
289 } else {
290 // Luckily, consumers of |maybe| only care whether the property
291 // was absent or not, so we can return a dummy |NONE| value
292 // for its attributes when it was present.
293 maybe = Just(found.FromJust() ? NONE : ABSENT);
294 }
295 }
Ben Murdoch85b71792012-04-11 18:30:58 +0100296 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 maybe = JSReceiver::GetPropertyAttributes(object, name);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100298 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300 if (!maybe.IsJust()) return Handle<Object>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 DCHECK(!isolate->has_pending_exception());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 *attributes = maybe.FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 if (maybe.FromJust() != ABSENT) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100305 if (FLAG_trace_contexts) {
306 PrintF("=> found property in context object %p\n",
307 reinterpret_cast<void*>(*object));
Ben Murdoch85b71792012-04-11 18:30:58 +0100308 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100309 return object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000310 }
311 }
312
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100313 // 2. Check the context proper if it has slots.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400314 if (context->IsFunctionContext() || context->IsBlockContext() ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315 context->IsScriptContext()) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100316 // Use serialized scope information of functions and blocks to search
317 // for the context index.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 Handle<ScopeInfo> scope_info(context->IsFunctionContext()
319 ? context->closure()->shared()->scope_info()
320 : context->scope_info());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100321 VariableMode mode;
322 InitializationFlag init_flag;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000323 // TODO(sigurds) Figure out whether maybe_assigned_flag should
324 // be used to compute binding_flags.
325 MaybeAssignedFlag maybe_assigned_flag;
326 int slot_index = ScopeInfo::ContextSlotIndex(
327 scope_info, name, &mode, &init_flag, &maybe_assigned_flag);
328 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100329 if (slot_index >= 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 if (FLAG_trace_contexts) {
331 PrintF("=> found local in context slot %d (mode = %d)\n",
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100332 slot_index, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000333 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100334 *index = slot_index;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335 GetAttributesAndBindingFlags(mode, init_flag, attributes,
336 binding_flags);
Steve Blocka7e24c12009-10-30 11:49:00 +0000337 return context;
338 }
339
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000340 // Check the slot corresponding to the intermediate context holding
341 // only the function name variable.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100342 if (follow_context_chain && context->IsFunctionContext()) {
343 VariableMode mode;
344 int function_index = scope_info->FunctionContextSlotIndex(*name, &mode);
345 if (function_index >= 0) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 if (FLAG_trace_contexts) {
347 PrintF("=> found intermediate function in context slot %d\n",
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100348 function_index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100350 *index = function_index;
Steve Blocka7e24c12009-10-30 11:49:00 +0000351 *attributes = READ_ONLY;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 DCHECK(mode == CONST_LEGACY || mode == CONST);
353 *binding_flags = (mode == CONST_LEGACY)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100354 ? IMMUTABLE_IS_INITIALIZED : IMMUTABLE_IS_INITIALIZED_HARMONY;
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 return context;
356 }
357 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100358
359 } else if (context->IsCatchContext()) {
360 // Catch contexts have the variable name in the extension slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 if (String::Equals(name, handle(context->catch_name()))) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100362 if (FLAG_trace_contexts) {
363 PrintF("=> found in catch context\n");
364 }
365 *index = Context::THROWN_OBJECT_INDEX;
366 *attributes = NONE;
367 *binding_flags = MUTABLE_IS_INITIALIZED;
368 return context;
369 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000370 }
371
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100372 // 3. Prepare to continue with the previous (next outermost) context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 if (context->IsNativeContext() ||
374 ((flags & STOP_AT_DECLARATION_SCOPE) != 0 &&
375 context->is_declaration_context())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 follow_context_chain = false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000377 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100378 context = Handle<Context>(context->previous(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000379 }
380 } while (follow_context_chain);
381
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 if (FLAG_trace_contexts) {
383 PrintF("=> no property/slot found\n");
384 }
385 return Handle<Object>::null();
386}
387
388
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000389void Context::InitializeGlobalSlots() {
390 DCHECK(IsScriptContext());
391 DisallowHeapAllocation no_gc;
392
393 ScopeInfo* scope_info = this->scope_info();
394
395 int context_globals = scope_info->ContextGlobalCount();
396 if (context_globals > 0) {
397 PropertyCell* empty_cell = GetHeap()->empty_property_cell();
398
399 int context_locals = scope_info->ContextLocalCount();
400 int index = Context::MIN_CONTEXT_SLOTS + context_locals;
401 for (int i = 0; i < context_globals; i++) {
402 set(index++, empty_cell);
403 }
404 }
405}
406
407
Ben Murdochb0fe1622011-05-05 13:52:32 +0100408void Context::AddOptimizedFunction(JSFunction* function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 DCHECK(IsNativeContext());
410#ifdef ENABLE_SLOW_DCHECKS
411 if (FLAG_enable_slow_asserts) {
412 Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
413 while (!element->IsUndefined()) {
414 CHECK(element != function);
415 element = JSFunction::cast(element)->next_function_link();
416 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100417 }
418
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419 // Check that the context belongs to the weak native contexts list.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100420 bool found = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421 Object* context = GetHeap()->native_contexts_list();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100422 while (!context->IsUndefined()) {
423 if (context == this) {
424 found = true;
425 break;
426 }
427 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK);
428 }
429 CHECK(found);
430#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431
432 // If the function link field is already used then the function was
433 // enqueued as a code flushing candidate and we remove it now.
434 if (!function->next_function_link()->IsUndefined()) {
435 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
436 flusher->EvictCandidate(function);
437 }
438
439 DCHECK(function->next_function_link()->IsUndefined());
440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 function->set_next_function_link(get(OPTIMIZED_FUNCTIONS_LIST),
442 UPDATE_WEAK_WRITE_BARRIER);
443 set(OPTIMIZED_FUNCTIONS_LIST, function, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100444}
445
446
447void Context::RemoveOptimizedFunction(JSFunction* function) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 DCHECK(IsNativeContext());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100449 Object* element = get(OPTIMIZED_FUNCTIONS_LIST);
450 JSFunction* prev = NULL;
451 while (!element->IsUndefined()) {
452 JSFunction* element_function = JSFunction::cast(element);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000453 DCHECK(element_function->next_function_link()->IsUndefined() ||
Ben Murdochb0fe1622011-05-05 13:52:32 +0100454 element_function->next_function_link()->IsJSFunction());
455 if (element_function == function) {
456 if (prev == NULL) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 set(OPTIMIZED_FUNCTIONS_LIST, element_function->next_function_link(),
458 UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100459 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 prev->set_next_function_link(element_function->next_function_link(),
461 UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100462 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463 element_function->set_next_function_link(GetHeap()->undefined_value(),
464 UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100465 return;
466 }
467 prev = element_function;
468 element = element_function->next_function_link();
469 }
470 UNREACHABLE();
471}
472
473
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000474void Context::SetOptimizedFunctionsListHead(Object* head) {
475 DCHECK(IsNativeContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 set(OPTIMIZED_FUNCTIONS_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477}
478
479
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480Object* Context::OptimizedFunctionsListHead() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000481 DCHECK(IsNativeContext());
Ben Murdochb0fe1622011-05-05 13:52:32 +0100482 return get(OPTIMIZED_FUNCTIONS_LIST);
483}
484
485
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486void Context::AddOptimizedCode(Code* code) {
487 DCHECK(IsNativeContext());
488 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
489 DCHECK(code->next_code_link()->IsUndefined());
490 code->set_next_code_link(get(OPTIMIZED_CODE_LIST));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491 set(OPTIMIZED_CODE_LIST, code, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000492}
493
494
495void Context::SetOptimizedCodeListHead(Object* head) {
496 DCHECK(IsNativeContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 set(OPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498}
499
500
501Object* Context::OptimizedCodeListHead() {
502 DCHECK(IsNativeContext());
503 return get(OPTIMIZED_CODE_LIST);
504}
505
506
507void Context::SetDeoptimizedCodeListHead(Object* head) {
508 DCHECK(IsNativeContext());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 set(DEOPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510}
511
512
513Object* Context::DeoptimizedCodeListHead() {
514 DCHECK(IsNativeContext());
515 return get(DEOPTIMIZED_CODE_LIST);
516}
517
518
519Handle<Object> Context::ErrorMessageForCodeGenerationFromStrings() {
520 Isolate* isolate = GetIsolate();
521 Handle<Object> result(error_message_for_code_gen_from_strings(), isolate);
522 if (!result->IsUndefined()) return result;
523 return isolate->factory()->NewStringFromStaticChars(
524 "Code generation from strings disallowed for this context");
Ben Murdochb0fe1622011-05-05 13:52:32 +0100525}
526
527
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528#define COMPARE_NAME(index, type, name) \
529 if (string->IsOneByteEqualTo(STATIC_CHAR_VECTOR(#name))) return index;
530
531int Context::ImportedFieldIndexForName(Handle<String> string) {
532 NATIVE_CONTEXT_IMPORTED_FIELDS(COMPARE_NAME)
533 return kNotFound;
534}
535
536
537int Context::IntrinsicIndexForName(Handle<String> string) {
538 NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(COMPARE_NAME);
539 return kNotFound;
540}
541
542#undef COMPARE_NAME
543
544
545bool Context::IsJSBuiltin(Handle<Context> native_context,
546 Handle<JSFunction> function) {
547#define COMPARE_FUNCTION(index, type, name) \
548 if (*function == native_context->get(index)) return true;
549 NATIVE_CONTEXT_JS_BUILTINS(COMPARE_FUNCTION);
550#undef COMPARE_FUNCTION
551 return false;
552}
553
554
Steve Blocka7e24c12009-10-30 11:49:00 +0000555#ifdef DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556
557bool Context::IsBootstrappingOrNativeContext(Isolate* isolate, Object* object) {
558 // During bootstrapping we allow all objects to pass as global
559 // objects. This is necessary to fix circular dependencies.
560 return isolate->heap()->gc_state() != Heap::NOT_IN_GC ||
561 isolate->bootstrapper()->IsActive() || object->IsNativeContext();
562}
563
564
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565bool Context::IsBootstrappingOrValidParentContext(
566 Object* object, Context* child) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000567 // During bootstrapping we allow all objects to pass as
568 // contexts. This is necessary to fix circular dependencies.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000569 if (child->GetIsolate()->bootstrapper()->IsActive()) return true;
570 if (!object->IsContext()) return false;
571 Context* context = Context::cast(object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400572 return context->IsNativeContext() || context->IsScriptContext() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 context->IsModuleContext() || !child->IsModuleContext();
Steve Blocka7e24c12009-10-30 11:49:00 +0000574}
575
Steve Blocka7e24c12009-10-30 11:49:00 +0000576#endif
577
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578
579void Context::IncrementErrorsThrown() {
580 DCHECK(IsNativeContext());
581
582 int previous_value = errors_thrown()->value();
583 set_errors_thrown(Smi::FromInt(previous_value + 1));
584}
585
586
587int Context::GetErrorsThrown() { return errors_thrown()->value(); }
588
589} // namespace internal
590} // namespace v8