blob: de0d66a74e4e1287798bf99f9707919850f9d8ce [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/runtime/runtime-utils.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006
7#include "src/accessors.h"
8#include "src/arguments.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/ast/scopeinfo.h"
10#include "src/ast/scopes.h"
11#include "src/deoptimizer.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012#include "src/frames-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000013#include "src/isolate-inl.h"
14#include "src/messages.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015
16namespace v8 {
17namespace internal {
18
19static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
20 HandleScope scope(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021 THROW_NEW_ERROR_RETURN_FAILURE(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023}
24
25
26RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
27 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028 THROW_NEW_ERROR_RETURN_FAILURE(isolate,
29 NewTypeError(MessageTemplate::kConstAssign));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040030}
31
32
33// May throw a RedeclarationError.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040035 Handle<String> name, Handle<Object> value,
36 PropertyAttributes attr, bool is_var,
37 bool is_const, bool is_function) {
38 Handle<ScriptContextTable> script_contexts(
39 global->native_context()->script_context_table());
40 ScriptContextTable::LookupResult lookup;
41 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
42 IsLexicalVariableMode(lookup.mode)) {
43 return ThrowRedeclarationError(isolate, name);
44 }
45
46 // Do the lookup own properties only, see ES5 erratum.
Ben Murdochda12d292016-06-02 14:46:10 +010047 LookupIterator it(global, name, global,
48 LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040049 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 if (!maybe.IsJust()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051
52 if (it.IsFound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054 // The name was declared before; check for conflicting re-declarations.
55 if (is_const) return ThrowRedeclarationError(isolate, name);
56
57 // Skip var re-declarations.
58 if (is_var) return isolate->heap()->undefined_value();
59
60 DCHECK(is_function);
61 if ((old_attributes & DONT_DELETE) != 0) {
62 // Only allow reconfiguring globals to functions in user code (no
63 // natives, which are marked as read-only).
64 DCHECK((attr & READ_ONLY) == 0);
65
66 // Check whether we can reconfigure the existing property into a
67 // function.
68 PropertyDetails old_details = it.property_details();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069 if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
Ben Murdoch097c5b22016-05-18 11:27:45 +010070 (it.state() == LookupIterator::ACCESSOR &&
71 it.GetAccessors()->IsAccessorPair())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040072 return ThrowRedeclarationError(isolate, name);
73 }
74 // If the existing property is not configurable, keep its attributes. Do
75 attr = old_attributes;
76 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010077
78 // If the current state is ACCESSOR, this could mean it's an AccessorInfo
79 // type property. We are not allowed to call into such setters during global
80 // function declaration since this would break e.g., onload. Meaning
81 // 'function onload() {}' would invalidly register that function as the
82 // onload callback. To avoid this situation, we first delete the property
83 // before readding it as a regular data property below.
84 if (it.state() == LookupIterator::ACCESSOR) it.Delete();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085 }
86
87 // Define or redefine own property.
Ben Murdoch097c5b22016-05-18 11:27:45 +010088 RETURN_FAILURE_ON_EXCEPTION(
89 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040090
91 return isolate->heap()->undefined_value();
92}
93
94
95RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
96 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 DCHECK_EQ(2, args.length());
98 Handle<JSGlobalObject> global(isolate->global_object());
99 Handle<Context> context(isolate->context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400100
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
102 CONVERT_SMI_ARG_CHECKED(flags, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400103
104 // Traverse the name/value pairs and set the properties.
105 int length = pairs->length();
Ben Murdochda12d292016-06-02 14:46:10 +0100106 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400107 Handle<String> name(String::cast(pairs->get(i)));
108 Handle<Object> initial_value(pairs->get(i + 1), isolate);
109
110 // We have to declare a global const property. To capture we only
111 // assign to it when evaluating the assignment for "const x =
112 // <expr>" the initial value is the hole.
113 bool is_var = initial_value->IsUndefined();
114 bool is_const = initial_value->IsTheHole();
115 bool is_function = initial_value->IsSharedFunctionInfo();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 DCHECK_EQ(1,
117 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118
119 Handle<Object> value;
120 if (is_function) {
121 // Copy the function and update its context. Use it as value.
122 Handle<SharedFunctionInfo> shared =
123 Handle<SharedFunctionInfo>::cast(initial_value);
124 Handle<JSFunction> function =
125 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
126 TENURED);
127 value = function;
128 } else {
129 value = isolate->factory()->undefined_value();
130 }
131
132 // Compute the property attributes. According to ECMA-262,
133 // the property must be non-configurable except in eval.
134 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
135 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
136 int attr = NONE;
137 if (is_const) attr |= READ_ONLY;
138 if (is_function && is_native) attr |= READ_ONLY;
139 if (!is_const && !is_eval) attr |= DONT_DELETE;
140
141 Object* result = DeclareGlobals(isolate, global, name, value,
142 static_cast<PropertyAttributes>(attr),
143 is_var, is_const, is_function);
144 if (isolate->has_pending_exception()) return result;
Ben Murdochda12d292016-06-02 14:46:10 +0100145 });
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400146
147 return isolate->heap()->undefined_value();
148}
149
150
151RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
152 HandleScope scope(isolate);
153 // args[0] == name
154 // args[1] == language_mode
155 // args[2] == value (optional)
156
157 // Determine if we need to assign to the variable if it already
158 // exists (based on the number of arguments).
159 RUNTIME_ASSERT(args.length() == 3);
160
161 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400163 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
164
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 Handle<JSGlobalObject> global(isolate->context()->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400166 Handle<Object> result;
167 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 isolate, result, Object::SetProperty(global, name, value, language_mode));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400169 return *result;
170}
171
172
173RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
174 HandleScope handle_scope(isolate);
175 // All constants are declared with an initial value. The name
176 // of the constant is the first argument and the initial value
177 // is the second.
178 RUNTIME_ASSERT(args.length() == 2);
179 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
180 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182 Handle<JSGlobalObject> global = isolate->global_object();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400183
184 // Lookup the property as own on the global object.
Ben Murdochda12d292016-06-02 14:46:10 +0100185 LookupIterator it(global, name, global,
186 LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400187 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 DCHECK(maybe.IsJust());
189 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400190
191 PropertyAttributes attr =
192 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
193 // Set the value if the property is either missing, or the property attributes
194 // allow setting the value without invoking an accessor.
195 if (it.IsFound()) {
196 // Ignore if we can't reconfigure the value.
197 if ((old_attributes & DONT_DELETE) != 0) {
198 if ((old_attributes & READ_ONLY) != 0 ||
199 it.state() == LookupIterator::ACCESSOR) {
200 return *value;
201 }
202 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
203 }
204 }
205
Ben Murdoch097c5b22016-05-18 11:27:45 +0100206 RETURN_FAILURE_ON_EXCEPTION(
207 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208
209 return *value;
210}
211
212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213namespace {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name,
216 Handle<Object> initial_value,
217 PropertyAttributes attr) {
218 // Declarations are always made in a function, eval or script context, or
219 // a declaration block scope.
220 // In the case of eval code, the context passed is the context of the caller,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400221 // which may be some nested context and not the declaration context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 Handle<Context> context_arg(isolate->context(), isolate);
223 Handle<Context> context(context_arg->declaration_context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400224
225 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
226 bool is_var = *initial_value == NULL;
227 bool is_const = initial_value->IsTheHole();
228 bool is_function = initial_value->IsJSFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 DCHECK_EQ(1,
230 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231
232 int index;
233 PropertyAttributes attributes;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234 BindingFlags binding_flags;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235
236 if ((attr & EVAL_DECLARED) != 0) {
237 // Check for a conflict with a lexically scoped variable
238 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
239 &binding_flags);
240 if (attributes != ABSENT &&
241 (binding_flags == MUTABLE_CHECK_INITIALIZED ||
242 binding_flags == IMMUTABLE_CHECK_INITIALIZED ||
243 binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) {
244 return ThrowRedeclarationError(isolate, name);
245 }
246 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
247 }
248
249 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
250 &attributes, &binding_flags);
251 if (holder.is_null()) {
252 // In case of JSProxy, an exception might have been thrown.
253 if (isolate->has_pending_exception()) return isolate->heap()->exception();
254 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400255
256 Handle<JSObject> object;
257 Handle<Object> value =
258 is_function ? initial_value
259 : Handle<Object>::cast(isolate->factory()->undefined_value());
260
261 // TODO(verwaest): This case should probably not be covered by this function,
262 // but by DeclareGlobals instead.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 if (attributes != ABSENT && holder->IsJSGlobalObject()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400264 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
265 value, attr, is_var, is_const, is_function);
266 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 if (context_arg->extension()->IsJSGlobalObject()) {
268 Handle<JSGlobalObject> global(
269 JSGlobalObject::cast(context_arg->extension()), isolate);
270 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
271 is_function);
272 } else if (context->IsScriptContext()) {
273 DCHECK(context->global_object()->IsJSGlobalObject());
274 Handle<JSGlobalObject> global(
275 JSGlobalObject::cast(context->global_object()), isolate);
276 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
277 is_function);
278 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279
280 if (attributes != ABSENT) {
281 // The name was declared before; check for conflicting re-declarations.
282 if (is_const || (attributes & READ_ONLY) != 0) {
283 return ThrowRedeclarationError(isolate, name);
284 }
285
286 // Skip var re-declarations.
287 if (is_var) return isolate->heap()->undefined_value();
288
289 DCHECK(is_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291 DCHECK(holder.is_identical_to(context));
292 context->set(index, *initial_value);
293 return isolate->heap()->undefined_value();
294 }
295
296 object = Handle<JSObject>::cast(holder);
297
298 } else if (context->has_extension()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299 // Sloppy varblock contexts might not have an extension object yet,
300 // in which case their extension is a ScopeInfo.
301 if (context->extension()->IsScopeInfo()) {
302 DCHECK(context->IsBlockContext());
303 object = isolate->factory()->NewJSObject(
304 isolate->context_extension_function());
305 Handle<HeapObject> extension =
306 isolate->factory()->NewSloppyBlockWithEvalContextExtension(
307 handle(context->scope_info()), object);
308 context->set_extension(*extension);
309 } else {
310 object = handle(context->extension_object(), isolate);
311 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400312 DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
313 } else {
314 DCHECK(context->IsFunctionContext());
315 object =
316 isolate->factory()->NewJSObject(isolate->context_extension_function());
317 context->set_extension(*object);
318 }
319
320 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
321 object, name, value, attr));
322
323 return isolate->heap()->undefined_value();
324}
325
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000326} // namespace
327
328
329RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
330 HandleScope scope(isolate);
331 DCHECK_EQ(3, args.length());
332 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
333 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1);
334 CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2);
335
336 PropertyAttributes attributes =
337 static_cast<PropertyAttributes>(property_attributes->value());
338 return DeclareLookupSlot(isolate, name, initial_value, attributes);
339}
340
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400341
342RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
343 HandleScope scope(isolate);
344 DCHECK(args.length() == 3);
345
346 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
347 DCHECK(!value->IsTheHole());
348 // Initializations are always done in a function or native context.
349 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
350 Handle<Context> context(context_arg->declaration_context());
351 CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
352
353 int index;
354 PropertyAttributes attributes;
355 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
356 BindingFlags binding_flags;
357 Handle<Object> holder =
358 context->Lookup(name, flags, &index, &attributes, &binding_flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 if (holder.is_null()) {
360 // In case of JSProxy, an exception might have been thrown.
361 if (isolate->has_pending_exception()) return isolate->heap()->exception();
362 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400365 DCHECK(holder->IsContext());
366 // Property was found in a context. Perform the assignment if the constant
367 // was uninitialized.
368 Handle<Context> context = Handle<Context>::cast(holder);
369 DCHECK((attributes & READ_ONLY) != 0);
370 if (context->get(index)->IsTheHole()) context->set(index, *value);
371 return *value;
372 }
373
374 PropertyAttributes attr =
375 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
376
377 // Strict mode handling not needed (legacy const is disallowed in strict
378 // mode).
379
380 // The declared const was configurable, and may have been deleted in the
381 // meanwhile. If so, re-introduce the variable in the context extension.
382 if (attributes == ABSENT) {
383 Handle<Context> declaration_context(context_arg->declaration_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 if (declaration_context->IsScriptContext()) {
385 holder = handle(declaration_context->global_object(), isolate);
386 } else {
387 holder = handle(declaration_context->extension_object(), isolate);
388 DCHECK(!holder.is_null());
389 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400390 CHECK(holder->IsJSObject());
391 } else {
392 // For JSContextExtensionObjects, the initializer can be run multiple times
393 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
394 // first assignment should go through. For JSGlobalObjects, additionally any
395 // code can run in between that modifies the declared property.
396 DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
397
Ben Murdochda12d292016-06-02 14:46:10 +0100398 LookupIterator it(holder, name, Handle<JSReceiver>::cast(holder),
399 LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401 if (!maybe.IsJust()) return isolate->heap()->exception();
402 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403
404 // Ignore if we can't reconfigure the value.
405 if ((old_attributes & DONT_DELETE) != 0) {
406 if ((old_attributes & READ_ONLY) != 0 ||
407 it.state() == LookupIterator::ACCESSOR) {
408 return *value;
409 }
410 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
411 }
412 }
413
414 RETURN_FAILURE_ON_EXCEPTION(
415 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
416 Handle<JSObject>::cast(holder), name, value, attr));
417
418 return *value;
419}
420
421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422namespace {
423
424// Find the arguments of the JavaScript function invocation that called
Ben Murdoch097c5b22016-05-18 11:27:45 +0100425// into C++ code. Collect these in a newly allocated array of handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000427 int* total_argc) {
428 // Find frame containing arguments passed to the caller.
429 JavaScriptFrameIterator it(isolate);
430 JavaScriptFrame* frame = it.frame();
431 List<JSFunction*> functions(2);
432 frame->GetFunctions(&functions);
433 if (functions.length() > 1) {
434 int inlined_jsframe_index = functions.length() - 1;
435 TranslatedState translated_values(frame);
436 translated_values.Prepare(false, frame->fp());
437
438 int argument_count = 0;
439 TranslatedFrame* translated_frame =
440 translated_values.GetArgumentsInfoFromJSFrameIndex(
441 inlined_jsframe_index, &argument_count);
442 TranslatedFrame::iterator iter = translated_frame->begin();
443
444 // Skip the function.
445 iter++;
446
447 // Skip the receiver.
448 iter++;
449 argument_count--;
450
Ben Murdoch097c5b22016-05-18 11:27:45 +0100451 *total_argc = argument_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 base::SmartArrayPointer<Handle<Object>> param_data(
453 NewArray<Handle<Object>>(*total_argc));
454 bool should_deoptimize = false;
455 for (int i = 0; i < argument_count; i++) {
456 should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
457 Handle<Object> value = iter->GetValue();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100458 param_data[i] = value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 iter++;
460 }
461
462 if (should_deoptimize) {
463 translated_values.StoreMaterializedValuesAndDeopt();
464 }
465
466 return param_data;
467 } else {
468 it.AdvanceToArgumentsFrame();
469 frame = it.frame();
470 int args_count = frame->ComputeParametersCount();
471
Ben Murdoch097c5b22016-05-18 11:27:45 +0100472 *total_argc = args_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 base::SmartArrayPointer<Handle<Object>> param_data(
474 NewArray<Handle<Object>>(*total_argc));
475 for (int i = 0; i < args_count; i++) {
476 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100477 param_data[i] = val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 }
479 return param_data;
480 }
481}
482
483
484template <typename T>
485Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
486 T parameters, int argument_count) {
487 CHECK(!IsSubclassConstructor(callee->shared()->kind()));
488 DCHECK(callee->shared()->has_simple_parameters());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400489 Handle<JSObject> result =
490 isolate->factory()->NewArgumentsObject(callee, argument_count);
491
492 // Allocate the elements if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000493 int parameter_count = callee->shared()->internal_formal_parameter_count();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400494 if (argument_count > 0) {
495 if (parameter_count > 0) {
496 int mapped_count = Min(argument_count, parameter_count);
497 Handle<FixedArray> parameter_map =
498 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
499 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 result->set_map(isolate->native_context()->fast_aliased_arguments_map());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400501 result->set_elements(*parameter_map);
502
503 // Store the context and the arguments array at the beginning of the
504 // parameter map.
505 Handle<Context> context(isolate->context());
506 Handle<FixedArray> arguments =
507 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
508 parameter_map->set(0, *context);
509 parameter_map->set(1, *arguments);
510
511 // Loop over the actual parameters backwards.
512 int index = argument_count - 1;
513 while (index >= mapped_count) {
514 // These go directly in the arguments array and have no
515 // corresponding slot in the parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400517 --index;
518 }
519
520 Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
521 while (index >= 0) {
522 // Detect duplicate names to the right in the parameter list.
523 Handle<String> name(scope_info->ParameterName(index));
524 int context_local_count = scope_info->ContextLocalCount();
525 bool duplicate = false;
526 for (int j = index + 1; j < parameter_count; ++j) {
527 if (scope_info->ParameterName(j) == *name) {
528 duplicate = true;
529 break;
530 }
531 }
532
533 if (duplicate) {
534 // This goes directly in the arguments array with a hole in the
535 // parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400537 parameter_map->set_the_hole(index + 2);
538 } else {
539 // The context index goes in the parameter map with a hole in the
540 // arguments array.
541 int context_index = -1;
542 for (int j = 0; j < context_local_count; ++j) {
543 if (scope_info->ContextLocalName(j) == *name) {
544 context_index = j;
545 break;
546 }
547 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400549 DCHECK(context_index >= 0);
550 arguments->set_the_hole(index);
551 parameter_map->set(
552 index + 2,
553 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
554 }
555
556 --index;
557 }
558 } else {
559 // If there is no aliasing, the arguments object elements are not
560 // special in any way.
561 Handle<FixedArray> elements =
562 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
563 result->set_elements(*elements);
564 for (int i = 0; i < argument_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 elements->set(i, parameters[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400566 }
567 }
568 }
569 return result;
570}
571
572
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573class HandleArguments BASE_EMBEDDED {
574 public:
575 explicit HandleArguments(Handle<Object>* array) : array_(array) {}
576 Object* operator[](int index) { return *array_[index]; }
577
578 private:
579 Handle<Object>* array_;
580};
581
582
583class ParameterArguments BASE_EMBEDDED {
584 public:
585 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
586 Object*& operator[](int index) { return *(parameters_ - index - 1); }
587
588 private:
589 Object** parameters_;
590};
591
592} // namespace
593
594
595RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400596 HandleScope scope(isolate);
597 DCHECK(args.length() == 1);
598 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 // This generic runtime function can also be used when the caller has been
600 // inlined, we use the slow but accurate {GetCallerArguments}.
601 int argument_count = 0;
602 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100603 GetCallerArguments(isolate, &argument_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 HandleArguments argument_getter(arguments.get());
605 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
606}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400607
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608
Ben Murdoch097c5b22016-05-18 11:27:45 +0100609RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100611 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
613 // This generic runtime function can also be used when the caller has been
614 // inlined, we use the slow but accurate {GetCallerArguments}.
615 int argument_count = 0;
616 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100617 GetCallerArguments(isolate, &argument_count);
618 Handle<JSObject> result =
619 isolate->factory()->NewArgumentsObject(callee, argument_count);
620 if (argument_count) {
621 Handle<FixedArray> array =
622 isolate->factory()->NewUninitializedFixedArray(argument_count);
623 DisallowHeapAllocation no_gc;
624 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
625 for (int i = 0; i < argument_count; i++) {
626 array->set(i, *arguments[i], mode);
627 }
628 result->set_elements(*array);
629 }
630 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631}
632
633
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634RUNTIME_FUNCTION(Runtime_NewRestParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100636 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100638 int start_index = callee->shared()->internal_formal_parameter_count();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 // This generic runtime function can also be used when the caller has been
640 // inlined, we use the slow but accurate {GetCallerArguments}.
641 int argument_count = 0;
642 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100643 GetCallerArguments(isolate, &argument_count);
644 int num_elements = std::max(0, argument_count - start_index);
Ben Murdochda12d292016-06-02 14:46:10 +0100645 Handle<JSObject> result =
646 isolate->factory()->NewJSArray(FAST_ELEMENTS, num_elements, num_elements,
647 DONT_INITIALIZE_ARRAY_ELEMENTS);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100648 {
649 DisallowHeapAllocation no_gc;
650 FixedArray* elements = FixedArray::cast(result->elements());
651 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
652 for (int i = 0; i < num_elements; i++) {
653 elements->set(i, *arguments[i + start_index], mode);
654 }
655 }
656 return *result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400657}
658
659
660RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
661 HandleScope scope(isolate);
662 DCHECK(args.length() == 3);
663 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
664 Object** parameters = reinterpret_cast<Object**>(args[1]);
665 CONVERT_SMI_ARG_CHECKED(argument_count, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666#ifdef DEBUG
667 // This runtime function does not materialize the correct arguments when the
668 // caller has been inlined, better make sure we are not hitting that case.
669 JavaScriptFrameIterator it(isolate);
670 DCHECK(!it.frame()->HasInlinedFrames());
671#endif // DEBUG
672 ParameterArguments argument_getter(parameters);
673 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400674}
675
676
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400677RUNTIME_FUNCTION(Runtime_NewClosure) {
678 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 DCHECK_EQ(1, args.length());
680 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
681 Handle<Context> context(isolate->context(), isolate);
682 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
683 NOT_TENURED);
684}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686
687RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
688 HandleScope scope(isolate);
689 DCHECK_EQ(1, args.length());
690 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
691 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400692 // The caller ensures that we pretenure closures that are assigned
693 // directly to properties.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400694 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695 TENURED);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400696}
697
698static Object* FindNameClash(Handle<ScopeInfo> scope_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 Handle<JSGlobalObject> global_object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400700 Handle<ScriptContextTable> script_context) {
701 Isolate* isolate = scope_info->GetIsolate();
702 for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
703 Handle<String> name(scope_info->ContextLocalName(var));
704 VariableMode mode = scope_info->ContextLocalMode(var);
705 ScriptContextTable::LookupResult lookup;
706 if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
707 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
708 return ThrowRedeclarationError(isolate, name);
709 }
710 }
711
712 if (IsLexicalVariableMode(mode)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100713 LookupIterator it(global_object, name, global_object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400714 LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
715 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 if (!maybe.IsJust()) return isolate->heap()->exception();
717 if ((maybe.FromJust() & DONT_DELETE) != 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400718 return ThrowRedeclarationError(isolate, name);
719 }
720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 JSGlobalObject::InvalidatePropertyCell(global_object, name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722 }
723 }
724 return isolate->heap()->undefined_value();
725}
726
727
728RUNTIME_FUNCTION(Runtime_NewScriptContext) {
729 HandleScope scope(isolate);
730 DCHECK(args.length() == 2);
731
732 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
733 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 Handle<JSGlobalObject> global_object(function->context()->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400735 Handle<Context> native_context(global_object->native_context());
736 Handle<ScriptContextTable> script_context_table(
737 native_context->script_context_table());
738
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400739 Object* name_clash_result =
740 FindNameClash(scope_info, global_object, script_context_table);
741 if (isolate->has_pending_exception()) return name_clash_result;
742
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 // Script contexts have a canonical empty function as their closure, not the
744 // anonymous closure containing the global code. See
745 // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
746 Handle<JSFunction> closure(
747 function->shared()->IsBuiltin() ? *function : native_context->closure());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400748 Handle<Context> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 isolate->factory()->NewScriptContext(closure, scope_info);
750
751 result->InitializeGlobalSlots();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400752
753 DCHECK(function->context() == isolate->context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 DCHECK(*global_object == result->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400755
756 Handle<ScriptContextTable> new_script_context_table =
757 ScriptContextTable::Extend(script_context_table, result);
758 native_context->set_script_context_table(*new_script_context_table);
759 return *result;
760}
761
762
763RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
764 HandleScope scope(isolate);
765 DCHECK(args.length() == 1);
766
767 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
768
769 DCHECK(function->context() == isolate->context());
770 int length = function->shared()->scope_info()->ContextLength();
771 return *isolate->factory()->NewFunctionContext(length, function);
772}
773
774
775RUNTIME_FUNCTION(Runtime_PushWithContext) {
776 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 DCHECK_EQ(2, args.length());
778 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
779 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400780 Handle<Context> current(isolate->context());
781 Handle<Context> context =
782 isolate->factory()->NewWithContext(function, current, extension_object);
783 isolate->set_context(*context);
784 return *context;
785}
786
787
788RUNTIME_FUNCTION(Runtime_PushCatchContext) {
789 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000790 DCHECK_EQ(3, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400791 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
792 CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400794 Handle<Context> current(isolate->context());
795 Handle<Context> context = isolate->factory()->NewCatchContext(
796 function, current, name, thrown_object);
797 isolate->set_context(*context);
798 return *context;
799}
800
801
802RUNTIME_FUNCTION(Runtime_PushBlockContext) {
803 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000804 DCHECK_EQ(2, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400805 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400807 Handle<Context> current(isolate->context());
808 Handle<Context> context =
809 isolate->factory()->NewBlockContext(function, current, scope_info);
810 isolate->set_context(*context);
811 return *context;
812}
813
814
815RUNTIME_FUNCTION(Runtime_IsJSModule) {
816 SealHandleScope shs(isolate);
817 DCHECK(args.length() == 1);
818 CONVERT_ARG_CHECKED(Object, obj, 0);
819 return isolate->heap()->ToBoolean(obj->IsJSModule());
820}
821
822
823RUNTIME_FUNCTION(Runtime_PushModuleContext) {
824 SealHandleScope shs(isolate);
825 DCHECK(args.length() == 2);
826 CONVERT_SMI_ARG_CHECKED(index, 0);
827
828 if (!args[1]->IsScopeInfo()) {
829 // Module already initialized. Find hosting context and retrieve context.
830 Context* host = Context::cast(isolate->context())->script_context();
831 Context* context = Context::cast(host->get(index));
832 DCHECK(context->previous() == isolate->context());
833 isolate->set_context(context);
834 return context;
835 }
836
837 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
838
839 // Allocate module context.
840 HandleScope scope(isolate);
841 Factory* factory = isolate->factory();
842 Handle<Context> context = factory->NewModuleContext(scope_info);
843 Handle<JSModule> module = factory->NewJSModule(context, scope_info);
844 context->set_module(*module);
845 Context* previous = isolate->context();
846 context->set_previous(previous);
847 context->set_closure(previous->closure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 context->set_native_context(previous->native_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400849 isolate->set_context(*context);
850
851 // Find hosting scope and initialize internal variable holding module there.
852 previous->script_context()->set(index, *context);
853
854 return *context;
855}
856
857
858RUNTIME_FUNCTION(Runtime_DeclareModules) {
859 HandleScope scope(isolate);
860 DCHECK(args.length() == 1);
861 CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
862 Context* host_context = isolate->context();
863
864 for (int i = 0; i < descriptions->length(); ++i) {
865 Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
866 int host_index = description->host_index();
867 Handle<Context> context(Context::cast(host_context->get(host_index)));
868 Handle<JSModule> module(context->module());
869
870 for (int j = 0; j < description->length(); ++j) {
871 Handle<String> name(description->name(j));
872 VariableMode mode = description->mode(j);
873 int index = description->index(j);
874 switch (mode) {
875 case VAR:
876 case LET:
877 case CONST:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 case CONST_LEGACY:
879 case IMPORT: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400880 PropertyAttributes attr =
881 IsImmutableVariableMode(mode) ? FROZEN : SEALED;
882 Handle<AccessorInfo> info =
883 Accessors::MakeModuleExport(name, index, attr);
884 Handle<Object> result =
885 JSObject::SetAccessor(module, info).ToHandleChecked();
886 DCHECK(!result->IsUndefined());
887 USE(result);
888 break;
889 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400890 case TEMPORARY:
891 case DYNAMIC:
892 case DYNAMIC_GLOBAL:
893 case DYNAMIC_LOCAL:
894 UNREACHABLE();
895 }
896 }
897
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000898 if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR)
899 .IsNothing()) {
900 DCHECK(false);
901 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400902 }
903
904 DCHECK(!isolate->has_pending_exception());
905 return isolate->heap()->undefined_value();
906}
907
908
909RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
910 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100911 DCHECK_EQ(1, args.length());
912 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400913
914 int index;
915 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100916 BindingFlags flags;
917 Handle<Object> holder = isolate->context()->Lookup(
918 name, FOLLOW_CHAINS, &index, &attributes, &flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400919
920 // If the slot was not found the result is true.
921 if (holder.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000922 // In case of JSProxy, an exception might have been thrown.
923 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400924 return isolate->heap()->true_value();
925 }
926
927 // If the slot was found in a context, it should be DONT_DELETE.
928 if (holder->IsContext()) {
929 return isolate->heap()->false_value();
930 }
931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 // The slot was found in a JSReceiver, either a context extension object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400933 // the global object, or the subject of a with. Try to delete it
934 // (respecting DONT_DELETE).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000935 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
936 Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
937 MAYBE_RETURN(result, isolate->heap()->exception());
938 return isolate->heap()->ToBoolean(result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400939}
940
941
Ben Murdoch097c5b22016-05-18 11:27:45 +0100942namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943
Ben Murdoch097c5b22016-05-18 11:27:45 +0100944MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
945 Object::ShouldThrow should_throw,
946 Handle<Object>* receiver_return = nullptr) {
947 Isolate* const isolate = name->GetIsolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400948
949 int index;
950 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100951 BindingFlags flags;
952 Handle<Object> holder = isolate->context()->Lookup(
953 name, FOLLOW_CHAINS, &index, &attributes, &flags);
954 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400955
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400957 DCHECK(holder->IsContext());
958 // If the "property" we were looking for is a local variable, the
959 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
960 Handle<Object> receiver = isolate->factory()->undefined_value();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100961 Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400962 // Check for uninitialized bindings.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100963 switch (flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400964 case MUTABLE_CHECK_INITIALIZED:
965 case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
966 if (value->IsTheHole()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100967 THROW_NEW_ERROR(isolate,
968 NewReferenceError(MessageTemplate::kNotDefined, name),
969 Object);
970 }
971 // FALLTHROUGH
972 case IMMUTABLE_CHECK_INITIALIZED:
973 if (value->IsTheHole()) {
974 DCHECK(attributes & READ_ONLY);
975 value = isolate->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400976 }
977 // FALLTHROUGH
978 case MUTABLE_IS_INITIALIZED:
979 case IMMUTABLE_IS_INITIALIZED:
980 case IMMUTABLE_IS_INITIALIZED_HARMONY:
981 DCHECK(!value->IsTheHole());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100982 if (receiver_return) *receiver_return = receiver;
983 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984 case MISSING_BINDING:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100985 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100987 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400988 }
989
990 // Otherwise, if the slot was found the holder is a context extension
991 // object, subject of a with, or a global object. We read the named
992 // property from it.
993 if (!holder.is_null()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400994 // No need to unhole the value here. This is taken care of by the
995 // GetProperty function.
996 Handle<Object> value;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100997 ASSIGN_RETURN_ON_EXCEPTION(
998 isolate, value, Object::GetProperty(holder, name),
999 Object);
1000 if (receiver_return) {
1001 *receiver_return =
1002 (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
1003 ? Handle<Object>::cast(isolate->factory()->undefined_value())
1004 : holder;
1005 }
1006 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001007 }
1008
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009 if (should_throw == Object::THROW_ON_ERROR) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001010 // The property doesn't exist - throw exception.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001011 THROW_NEW_ERROR(
1012 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001013 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001014
1015 // The property doesn't exist - return undefined.
1016 if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
1017 return isolate->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001018}
1019
Ben Murdoch097c5b22016-05-18 11:27:45 +01001020} // namespace
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001021
1022
Ben Murdoch097c5b22016-05-18 11:27:45 +01001023RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001024 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001025 DCHECK_EQ(1, args.length());
1026 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1027 Handle<Object> value;
1028 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1029 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR));
1030 return *value;
1031}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001032
Ben Murdoch097c5b22016-05-18 11:27:45 +01001033
1034RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
1035 HandleScope scope(isolate);
1036 DCHECK_EQ(1, args.length());
1037 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1038 Handle<Object> value;
1039 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1040 isolate, value, LoadLookupSlot(name, Object::DONT_THROW));
1041 return *value;
1042}
1043
1044
1045RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) {
1046 HandleScope scope(isolate);
1047 DCHECK_EQ(1, args.length());
1048 DCHECK(args[0]->IsString());
1049 Handle<String> name = args.at<String>(0);
1050 Handle<Object> value;
1051 Handle<Object> receiver;
1052 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1053 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver),
1054 MakePair(isolate->heap()->exception(), nullptr));
1055 return MakePair(*value, *receiver);
1056}
1057
1058
1059namespace {
1060
1061MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
1062 LanguageMode language_mode) {
1063 Isolate* const isolate = name->GetIsolate();
1064 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001065
1066 int index;
1067 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001068 BindingFlags flags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001069 Handle<Object> holder =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001070 context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001071 if (holder.is_null()) {
1072 // In case of JSProxy, an exception might have been thrown.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001073 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001075
1076 // The property was found in a context slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 if (index != Context::kNotFound) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001078 if ((flags == MUTABLE_CHECK_INITIALIZED ||
1079 flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 Handle<Context>::cast(holder)->is_the_hole(index)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001081 THROW_NEW_ERROR(isolate,
1082 NewReferenceError(MessageTemplate::kNotDefined, name),
1083 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001084 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001085 if ((attributes & READ_ONLY) == 0) {
1086 Handle<Context>::cast(holder)->set(index, *value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 } else if (is_strict(language_mode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001088 // Setting read only property in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001089 THROW_NEW_ERROR(isolate,
1090 NewTypeError(MessageTemplate::kStrictCannotAssign, name),
1091 Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001092 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001093 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001094 }
1095
1096 // Slow case: The property is not in a context slot. It is either in a
1097 // context extension object, a property of the subject of a with, or a
1098 // property of the global object.
1099 Handle<JSReceiver> object;
1100 if (attributes != ABSENT) {
1101 // The property exists on the holder.
1102 object = Handle<JSReceiver>::cast(holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001103 } else if (is_strict(language_mode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001104 // If absent in strict mode: throw.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001105 THROW_NEW_ERROR(
1106 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001107 } else {
1108 // If absent in sloppy mode: add the property to the global object.
1109 object = Handle<JSReceiver>(context->global_object());
1110 }
1111
Ben Murdoch097c5b22016-05-18 11:27:45 +01001112 ASSIGN_RETURN_ON_EXCEPTION(
1113 isolate, value, Object::SetProperty(object, name, value, language_mode),
1114 Object);
1115 return value;
1116}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001117
Ben Murdoch097c5b22016-05-18 11:27:45 +01001118} // namespace
1119
1120
1121RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) {
1122 HandleScope scope(isolate);
1123 DCHECK_EQ(2, args.length());
1124 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1125 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1126 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1127 StoreLookupSlot(name, value, SLOPPY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001128 return *value;
1129}
1130
1131
Ben Murdoch097c5b22016-05-18 11:27:45 +01001132RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001134 DCHECK_EQ(2, args.length());
1135 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1136 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1137 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1138 StoreLookupSlot(name, value, STRICT));
1139 return *value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140}
1141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142} // namespace internal
1143} // namespace v8