blob: a8f3a749189196663b9f086725dc700df185b13e [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.
47 LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
48 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 if (!maybe.IsJust()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050
51 if (it.IsFound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040053 // The name was declared before; check for conflicting re-declarations.
54 if (is_const) return ThrowRedeclarationError(isolate, name);
55
56 // Skip var re-declarations.
57 if (is_var) return isolate->heap()->undefined_value();
58
59 DCHECK(is_function);
60 if ((old_attributes & DONT_DELETE) != 0) {
61 // Only allow reconfiguring globals to functions in user code (no
62 // natives, which are marked as read-only).
63 DCHECK((attr & READ_ONLY) == 0);
64
65 // Check whether we can reconfigure the existing property into a
66 // function.
67 PropertyDetails old_details = it.property_details();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040068 if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
Ben Murdoch097c5b22016-05-18 11:27:45 +010069 (it.state() == LookupIterator::ACCESSOR &&
70 it.GetAccessors()->IsAccessorPair())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040071 return ThrowRedeclarationError(isolate, name);
72 }
73 // If the existing property is not configurable, keep its attributes. Do
74 attr = old_attributes;
75 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010076
77 // If the current state is ACCESSOR, this could mean it's an AccessorInfo
78 // type property. We are not allowed to call into such setters during global
79 // function declaration since this would break e.g., onload. Meaning
80 // 'function onload() {}' would invalidly register that function as the
81 // onload callback. To avoid this situation, we first delete the property
82 // before readding it as a regular data property below.
83 if (it.state() == LookupIterator::ACCESSOR) it.Delete();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084 }
85
86 // Define or redefine own property.
Ben Murdoch097c5b22016-05-18 11:27:45 +010087 RETURN_FAILURE_ON_EXCEPTION(
88 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040089
90 return isolate->heap()->undefined_value();
91}
92
93
94RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
95 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096 DCHECK_EQ(2, args.length());
97 Handle<JSGlobalObject> global(isolate->global_object());
98 Handle<Context> context(isolate->context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
101 CONVERT_SMI_ARG_CHECKED(flags, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400102
103 // Traverse the name/value pairs and set the properties.
104 int length = pairs->length();
105 for (int i = 0; i < length; i += 2) {
106 HandleScope scope(isolate);
107 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;
145 }
146
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.
185 LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
186 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 DCHECK(maybe.IsJust());
188 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400189
190 PropertyAttributes attr =
191 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
192 // Set the value if the property is either missing, or the property attributes
193 // allow setting the value without invoking an accessor.
194 if (it.IsFound()) {
195 // Ignore if we can't reconfigure the value.
196 if ((old_attributes & DONT_DELETE) != 0) {
197 if ((old_attributes & READ_ONLY) != 0 ||
198 it.state() == LookupIterator::ACCESSOR) {
199 return *value;
200 }
201 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
202 }
203 }
204
Ben Murdoch097c5b22016-05-18 11:27:45 +0100205 RETURN_FAILURE_ON_EXCEPTION(
206 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400207
208 return *value;
209}
210
211
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212namespace {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name,
215 Handle<Object> initial_value,
216 PropertyAttributes attr) {
217 // Declarations are always made in a function, eval or script context, or
218 // a declaration block scope.
219 // In the case of eval code, the context passed is the context of the caller,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220 // which may be some nested context and not the declaration context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 Handle<Context> context_arg(isolate->context(), isolate);
222 Handle<Context> context(context_arg->declaration_context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400223
224 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
225 bool is_var = *initial_value == NULL;
226 bool is_const = initial_value->IsTheHole();
227 bool is_function = initial_value->IsJSFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 DCHECK_EQ(1,
229 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400230
231 int index;
232 PropertyAttributes attributes;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233 BindingFlags binding_flags;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234
235 if ((attr & EVAL_DECLARED) != 0) {
236 // Check for a conflict with a lexically scoped variable
237 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
238 &binding_flags);
239 if (attributes != ABSENT &&
240 (binding_flags == MUTABLE_CHECK_INITIALIZED ||
241 binding_flags == IMMUTABLE_CHECK_INITIALIZED ||
242 binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) {
243 return ThrowRedeclarationError(isolate, name);
244 }
245 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
246 }
247
248 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
249 &attributes, &binding_flags);
250 if (holder.is_null()) {
251 // In case of JSProxy, an exception might have been thrown.
252 if (isolate->has_pending_exception()) return isolate->heap()->exception();
253 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254
255 Handle<JSObject> object;
256 Handle<Object> value =
257 is_function ? initial_value
258 : Handle<Object>::cast(isolate->factory()->undefined_value());
259
260 // TODO(verwaest): This case should probably not be covered by this function,
261 // but by DeclareGlobals instead.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 if (attributes != ABSENT && holder->IsJSGlobalObject()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400263 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
264 value, attr, is_var, is_const, is_function);
265 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 if (context_arg->extension()->IsJSGlobalObject()) {
267 Handle<JSGlobalObject> global(
268 JSGlobalObject::cast(context_arg->extension()), isolate);
269 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
270 is_function);
271 } else if (context->IsScriptContext()) {
272 DCHECK(context->global_object()->IsJSGlobalObject());
273 Handle<JSGlobalObject> global(
274 JSGlobalObject::cast(context->global_object()), isolate);
275 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
276 is_function);
277 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400278
279 if (attributes != ABSENT) {
280 // The name was declared before; check for conflicting re-declarations.
281 if (is_const || (attributes & READ_ONLY) != 0) {
282 return ThrowRedeclarationError(isolate, name);
283 }
284
285 // Skip var re-declarations.
286 if (is_var) return isolate->heap()->undefined_value();
287
288 DCHECK(is_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400290 DCHECK(holder.is_identical_to(context));
291 context->set(index, *initial_value);
292 return isolate->heap()->undefined_value();
293 }
294
295 object = Handle<JSObject>::cast(holder);
296
297 } else if (context->has_extension()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000298 // Sloppy varblock contexts might not have an extension object yet,
299 // in which case their extension is a ScopeInfo.
300 if (context->extension()->IsScopeInfo()) {
301 DCHECK(context->IsBlockContext());
302 object = isolate->factory()->NewJSObject(
303 isolate->context_extension_function());
304 Handle<HeapObject> extension =
305 isolate->factory()->NewSloppyBlockWithEvalContextExtension(
306 handle(context->scope_info()), object);
307 context->set_extension(*extension);
308 } else {
309 object = handle(context->extension_object(), isolate);
310 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400311 DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
312 } else {
313 DCHECK(context->IsFunctionContext());
314 object =
315 isolate->factory()->NewJSObject(isolate->context_extension_function());
316 context->set_extension(*object);
317 }
318
319 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
320 object, name, value, attr));
321
322 return isolate->heap()->undefined_value();
323}
324
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325} // namespace
326
327
328RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
329 HandleScope scope(isolate);
330 DCHECK_EQ(3, args.length());
331 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
332 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1);
333 CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2);
334
335 PropertyAttributes attributes =
336 static_cast<PropertyAttributes>(property_attributes->value());
337 return DeclareLookupSlot(isolate, name, initial_value, attributes);
338}
339
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340
341RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
342 HandleScope scope(isolate);
343 DCHECK(args.length() == 3);
344
345 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
346 DCHECK(!value->IsTheHole());
347 // Initializations are always done in a function or native context.
348 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
349 Handle<Context> context(context_arg->declaration_context());
350 CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
351
352 int index;
353 PropertyAttributes attributes;
354 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
355 BindingFlags binding_flags;
356 Handle<Object> holder =
357 context->Lookup(name, flags, &index, &attributes, &binding_flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358 if (holder.is_null()) {
359 // In case of JSProxy, an exception might have been thrown.
360 if (isolate->has_pending_exception()) return isolate->heap()->exception();
361 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400364 DCHECK(holder->IsContext());
365 // Property was found in a context. Perform the assignment if the constant
366 // was uninitialized.
367 Handle<Context> context = Handle<Context>::cast(holder);
368 DCHECK((attributes & READ_ONLY) != 0);
369 if (context->get(index)->IsTheHole()) context->set(index, *value);
370 return *value;
371 }
372
373 PropertyAttributes attr =
374 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
375
376 // Strict mode handling not needed (legacy const is disallowed in strict
377 // mode).
378
379 // The declared const was configurable, and may have been deleted in the
380 // meanwhile. If so, re-introduce the variable in the context extension.
381 if (attributes == ABSENT) {
382 Handle<Context> declaration_context(context_arg->declaration_context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 if (declaration_context->IsScriptContext()) {
384 holder = handle(declaration_context->global_object(), isolate);
385 } else {
386 holder = handle(declaration_context->extension_object(), isolate);
387 DCHECK(!holder.is_null());
388 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400389 CHECK(holder->IsJSObject());
390 } else {
391 // For JSContextExtensionObjects, the initializer can be run multiple times
392 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
393 // first assignment should go through. For JSGlobalObjects, additionally any
394 // code can run in between that modifies the declared property.
395 DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
396
397 LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
398 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 if (!maybe.IsJust()) return isolate->heap()->exception();
400 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400401
402 // Ignore if we can't reconfigure the value.
403 if ((old_attributes & DONT_DELETE) != 0) {
404 if ((old_attributes & READ_ONLY) != 0 ||
405 it.state() == LookupIterator::ACCESSOR) {
406 return *value;
407 }
408 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
409 }
410 }
411
412 RETURN_FAILURE_ON_EXCEPTION(
413 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
414 Handle<JSObject>::cast(holder), name, value, attr));
415
416 return *value;
417}
418
419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420namespace {
421
422// Find the arguments of the JavaScript function invocation that called
Ben Murdoch097c5b22016-05-18 11:27:45 +0100423// into C++ code. Collect these in a newly allocated array of handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 int* total_argc) {
426 // Find frame containing arguments passed to the caller.
427 JavaScriptFrameIterator it(isolate);
428 JavaScriptFrame* frame = it.frame();
429 List<JSFunction*> functions(2);
430 frame->GetFunctions(&functions);
431 if (functions.length() > 1) {
432 int inlined_jsframe_index = functions.length() - 1;
433 TranslatedState translated_values(frame);
434 translated_values.Prepare(false, frame->fp());
435
436 int argument_count = 0;
437 TranslatedFrame* translated_frame =
438 translated_values.GetArgumentsInfoFromJSFrameIndex(
439 inlined_jsframe_index, &argument_count);
440 TranslatedFrame::iterator iter = translated_frame->begin();
441
442 // Skip the function.
443 iter++;
444
445 // Skip the receiver.
446 iter++;
447 argument_count--;
448
Ben Murdoch097c5b22016-05-18 11:27:45 +0100449 *total_argc = argument_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 base::SmartArrayPointer<Handle<Object>> param_data(
451 NewArray<Handle<Object>>(*total_argc));
452 bool should_deoptimize = false;
453 for (int i = 0; i < argument_count; i++) {
454 should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
455 Handle<Object> value = iter->GetValue();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100456 param_data[i] = value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 iter++;
458 }
459
460 if (should_deoptimize) {
461 translated_values.StoreMaterializedValuesAndDeopt();
462 }
463
464 return param_data;
465 } else {
466 it.AdvanceToArgumentsFrame();
467 frame = it.frame();
468 int args_count = frame->ComputeParametersCount();
469
Ben Murdoch097c5b22016-05-18 11:27:45 +0100470 *total_argc = args_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 base::SmartArrayPointer<Handle<Object>> param_data(
472 NewArray<Handle<Object>>(*total_argc));
473 for (int i = 0; i < args_count; i++) {
474 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100475 param_data[i] = val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 }
477 return param_data;
478 }
479}
480
481
482template <typename T>
483Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
484 T parameters, int argument_count) {
485 CHECK(!IsSubclassConstructor(callee->shared()->kind()));
486 DCHECK(callee->shared()->has_simple_parameters());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400487 Handle<JSObject> result =
488 isolate->factory()->NewArgumentsObject(callee, argument_count);
489
490 // Allocate the elements if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491 int parameter_count = callee->shared()->internal_formal_parameter_count();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400492 if (argument_count > 0) {
493 if (parameter_count > 0) {
494 int mapped_count = Min(argument_count, parameter_count);
495 Handle<FixedArray> parameter_map =
496 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
497 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000498 result->set_map(isolate->native_context()->fast_aliased_arguments_map());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400499 result->set_elements(*parameter_map);
500
501 // Store the context and the arguments array at the beginning of the
502 // parameter map.
503 Handle<Context> context(isolate->context());
504 Handle<FixedArray> arguments =
505 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
506 parameter_map->set(0, *context);
507 parameter_map->set(1, *arguments);
508
509 // Loop over the actual parameters backwards.
510 int index = argument_count - 1;
511 while (index >= mapped_count) {
512 // These go directly in the arguments array and have no
513 // corresponding slot in the parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400515 --index;
516 }
517
518 Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
519 while (index >= 0) {
520 // Detect duplicate names to the right in the parameter list.
521 Handle<String> name(scope_info->ParameterName(index));
522 int context_local_count = scope_info->ContextLocalCount();
523 bool duplicate = false;
524 for (int j = index + 1; j < parameter_count; ++j) {
525 if (scope_info->ParameterName(j) == *name) {
526 duplicate = true;
527 break;
528 }
529 }
530
531 if (duplicate) {
532 // This goes directly in the arguments array with a hole in the
533 // parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400535 parameter_map->set_the_hole(index + 2);
536 } else {
537 // The context index goes in the parameter map with a hole in the
538 // arguments array.
539 int context_index = -1;
540 for (int j = 0; j < context_local_count; ++j) {
541 if (scope_info->ContextLocalName(j) == *name) {
542 context_index = j;
543 break;
544 }
545 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400547 DCHECK(context_index >= 0);
548 arguments->set_the_hole(index);
549 parameter_map->set(
550 index + 2,
551 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
552 }
553
554 --index;
555 }
556 } else {
557 // If there is no aliasing, the arguments object elements are not
558 // special in any way.
559 Handle<FixedArray> elements =
560 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
561 result->set_elements(*elements);
562 for (int i = 0; i < argument_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 elements->set(i, parameters[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400564 }
565 }
566 }
567 return result;
568}
569
570
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571class HandleArguments BASE_EMBEDDED {
572 public:
573 explicit HandleArguments(Handle<Object>* array) : array_(array) {}
574 Object* operator[](int index) { return *array_[index]; }
575
576 private:
577 Handle<Object>* array_;
578};
579
580
581class ParameterArguments BASE_EMBEDDED {
582 public:
583 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
584 Object*& operator[](int index) { return *(parameters_ - index - 1); }
585
586 private:
587 Object** parameters_;
588};
589
590} // namespace
591
592
593RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400594 HandleScope scope(isolate);
595 DCHECK(args.length() == 1);
596 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 // This generic runtime function can also be used when the caller has been
598 // inlined, we use the slow but accurate {GetCallerArguments}.
599 int argument_count = 0;
600 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100601 GetCallerArguments(isolate, &argument_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 HandleArguments argument_getter(arguments.get());
603 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
604}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400605
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400606
Ben Murdoch097c5b22016-05-18 11:27:45 +0100607RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100609 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
611 // This generic runtime function can also be used when the caller has been
612 // inlined, we use the slow but accurate {GetCallerArguments}.
613 int argument_count = 0;
614 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100615 GetCallerArguments(isolate, &argument_count);
616 Handle<JSObject> result =
617 isolate->factory()->NewArgumentsObject(callee, argument_count);
618 if (argument_count) {
619 Handle<FixedArray> array =
620 isolate->factory()->NewUninitializedFixedArray(argument_count);
621 DisallowHeapAllocation no_gc;
622 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
623 for (int i = 0; i < argument_count; i++) {
624 array->set(i, *arguments[i], mode);
625 }
626 result->set_elements(*array);
627 }
628 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000629}
630
631
Ben Murdoch097c5b22016-05-18 11:27:45 +0100632RUNTIME_FUNCTION(Runtime_NewRestParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100636 int start_index = callee->shared()->internal_formal_parameter_count();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 // This generic runtime function can also be used when the caller has been
638 // inlined, we use the slow but accurate {GetCallerArguments}.
639 int argument_count = 0;
640 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100641 GetCallerArguments(isolate, &argument_count);
642 int num_elements = std::max(0, argument_count - start_index);
643 Handle<JSObject> result = isolate->factory()->NewJSArray(
644 FAST_ELEMENTS, num_elements, num_elements, Strength::WEAK,
645 DONT_INITIALIZE_ARRAY_ELEMENTS);
646 {
647 DisallowHeapAllocation no_gc;
648 FixedArray* elements = FixedArray::cast(result->elements());
649 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
650 for (int i = 0; i < num_elements; i++) {
651 elements->set(i, *arguments[i + start_index], mode);
652 }
653 }
654 return *result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400655}
656
657
658RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
659 HandleScope scope(isolate);
660 DCHECK(args.length() == 3);
661 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
662 Object** parameters = reinterpret_cast<Object**>(args[1]);
663 CONVERT_SMI_ARG_CHECKED(argument_count, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664#ifdef DEBUG
665 // This runtime function does not materialize the correct arguments when the
666 // caller has been inlined, better make sure we are not hitting that case.
667 JavaScriptFrameIterator it(isolate);
668 DCHECK(!it.frame()->HasInlinedFrames());
669#endif // DEBUG
670 ParameterArguments argument_getter(parameters);
671 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400672}
673
674
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400675RUNTIME_FUNCTION(Runtime_NewClosure) {
676 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677 DCHECK_EQ(1, args.length());
678 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
679 Handle<Context> context(isolate->context(), isolate);
680 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
681 NOT_TENURED);
682}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684
685RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
686 HandleScope scope(isolate);
687 DCHECK_EQ(1, args.length());
688 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
689 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400690 // The caller ensures that we pretenure closures that are assigned
691 // directly to properties.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400692 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 TENURED);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400694}
695
696static Object* FindNameClash(Handle<ScopeInfo> scope_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 Handle<JSGlobalObject> global_object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400698 Handle<ScriptContextTable> script_context) {
699 Isolate* isolate = scope_info->GetIsolate();
700 for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
701 Handle<String> name(scope_info->ContextLocalName(var));
702 VariableMode mode = scope_info->ContextLocalMode(var);
703 ScriptContextTable::LookupResult lookup;
704 if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
705 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
706 return ThrowRedeclarationError(isolate, name);
707 }
708 }
709
710 if (IsLexicalVariableMode(mode)) {
711 LookupIterator it(global_object, name,
712 LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
713 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 if (!maybe.IsJust()) return isolate->heap()->exception();
715 if ((maybe.FromJust() & DONT_DELETE) != 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400716 return ThrowRedeclarationError(isolate, name);
717 }
718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719 JSGlobalObject::InvalidatePropertyCell(global_object, name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400720 }
721 }
722 return isolate->heap()->undefined_value();
723}
724
725
726RUNTIME_FUNCTION(Runtime_NewScriptContext) {
727 HandleScope scope(isolate);
728 DCHECK(args.length() == 2);
729
730 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
731 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732 Handle<JSGlobalObject> global_object(function->context()->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400733 Handle<Context> native_context(global_object->native_context());
734 Handle<ScriptContextTable> script_context_table(
735 native_context->script_context_table());
736
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 Object* name_clash_result =
738 FindNameClash(scope_info, global_object, script_context_table);
739 if (isolate->has_pending_exception()) return name_clash_result;
740
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 // Script contexts have a canonical empty function as their closure, not the
742 // anonymous closure containing the global code. See
743 // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
744 Handle<JSFunction> closure(
745 function->shared()->IsBuiltin() ? *function : native_context->closure());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400746 Handle<Context> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 isolate->factory()->NewScriptContext(closure, scope_info);
748
749 result->InitializeGlobalSlots();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400750
751 DCHECK(function->context() == isolate->context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 DCHECK(*global_object == result->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400753
754 Handle<ScriptContextTable> new_script_context_table =
755 ScriptContextTable::Extend(script_context_table, result);
756 native_context->set_script_context_table(*new_script_context_table);
757 return *result;
758}
759
760
761RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
762 HandleScope scope(isolate);
763 DCHECK(args.length() == 1);
764
765 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
766
767 DCHECK(function->context() == isolate->context());
768 int length = function->shared()->scope_info()->ContextLength();
769 return *isolate->factory()->NewFunctionContext(length, function);
770}
771
772
773RUNTIME_FUNCTION(Runtime_PushWithContext) {
774 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 DCHECK_EQ(2, args.length());
776 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
777 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400778 Handle<Context> current(isolate->context());
779 Handle<Context> context =
780 isolate->factory()->NewWithContext(function, current, extension_object);
781 isolate->set_context(*context);
782 return *context;
783}
784
785
786RUNTIME_FUNCTION(Runtime_PushCatchContext) {
787 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788 DCHECK_EQ(3, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400789 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
790 CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400792 Handle<Context> current(isolate->context());
793 Handle<Context> context = isolate->factory()->NewCatchContext(
794 function, current, name, thrown_object);
795 isolate->set_context(*context);
796 return *context;
797}
798
799
800RUNTIME_FUNCTION(Runtime_PushBlockContext) {
801 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 DCHECK_EQ(2, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400803 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000804 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400805 Handle<Context> current(isolate->context());
806 Handle<Context> context =
807 isolate->factory()->NewBlockContext(function, current, scope_info);
808 isolate->set_context(*context);
809 return *context;
810}
811
812
813RUNTIME_FUNCTION(Runtime_IsJSModule) {
814 SealHandleScope shs(isolate);
815 DCHECK(args.length() == 1);
816 CONVERT_ARG_CHECKED(Object, obj, 0);
817 return isolate->heap()->ToBoolean(obj->IsJSModule());
818}
819
820
821RUNTIME_FUNCTION(Runtime_PushModuleContext) {
822 SealHandleScope shs(isolate);
823 DCHECK(args.length() == 2);
824 CONVERT_SMI_ARG_CHECKED(index, 0);
825
826 if (!args[1]->IsScopeInfo()) {
827 // Module already initialized. Find hosting context and retrieve context.
828 Context* host = Context::cast(isolate->context())->script_context();
829 Context* context = Context::cast(host->get(index));
830 DCHECK(context->previous() == isolate->context());
831 isolate->set_context(context);
832 return context;
833 }
834
835 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
836
837 // Allocate module context.
838 HandleScope scope(isolate);
839 Factory* factory = isolate->factory();
840 Handle<Context> context = factory->NewModuleContext(scope_info);
841 Handle<JSModule> module = factory->NewJSModule(context, scope_info);
842 context->set_module(*module);
843 Context* previous = isolate->context();
844 context->set_previous(previous);
845 context->set_closure(previous->closure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000846 context->set_native_context(previous->native_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400847 isolate->set_context(*context);
848
849 // Find hosting scope and initialize internal variable holding module there.
850 previous->script_context()->set(index, *context);
851
852 return *context;
853}
854
855
856RUNTIME_FUNCTION(Runtime_DeclareModules) {
857 HandleScope scope(isolate);
858 DCHECK(args.length() == 1);
859 CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
860 Context* host_context = isolate->context();
861
862 for (int i = 0; i < descriptions->length(); ++i) {
863 Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
864 int host_index = description->host_index();
865 Handle<Context> context(Context::cast(host_context->get(host_index)));
866 Handle<JSModule> module(context->module());
867
868 for (int j = 0; j < description->length(); ++j) {
869 Handle<String> name(description->name(j));
870 VariableMode mode = description->mode(j);
871 int index = description->index(j);
872 switch (mode) {
873 case VAR:
874 case LET:
875 case CONST:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 case CONST_LEGACY:
877 case IMPORT: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400878 PropertyAttributes attr =
879 IsImmutableVariableMode(mode) ? FROZEN : SEALED;
880 Handle<AccessorInfo> info =
881 Accessors::MakeModuleExport(name, index, attr);
882 Handle<Object> result =
883 JSObject::SetAccessor(module, info).ToHandleChecked();
884 DCHECK(!result->IsUndefined());
885 USE(result);
886 break;
887 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400888 case TEMPORARY:
889 case DYNAMIC:
890 case DYNAMIC_GLOBAL:
891 case DYNAMIC_LOCAL:
892 UNREACHABLE();
893 }
894 }
895
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR)
897 .IsNothing()) {
898 DCHECK(false);
899 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400900 }
901
902 DCHECK(!isolate->has_pending_exception());
903 return isolate->heap()->undefined_value();
904}
905
906
907RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
908 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100909 DCHECK_EQ(1, args.length());
910 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400911
912 int index;
913 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100914 BindingFlags flags;
915 Handle<Object> holder = isolate->context()->Lookup(
916 name, FOLLOW_CHAINS, &index, &attributes, &flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400917
918 // If the slot was not found the result is true.
919 if (holder.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 // In case of JSProxy, an exception might have been thrown.
921 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400922 return isolate->heap()->true_value();
923 }
924
925 // If the slot was found in a context, it should be DONT_DELETE.
926 if (holder->IsContext()) {
927 return isolate->heap()->false_value();
928 }
929
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930 // The slot was found in a JSReceiver, either a context extension object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400931 // the global object, or the subject of a with. Try to delete it
932 // (respecting DONT_DELETE).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000933 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
934 Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
935 MAYBE_RETURN(result, isolate->heap()->exception());
936 return isolate->heap()->ToBoolean(result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400937}
938
939
Ben Murdoch097c5b22016-05-18 11:27:45 +0100940namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941
Ben Murdoch097c5b22016-05-18 11:27:45 +0100942MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
943 Object::ShouldThrow should_throw,
944 Handle<Object>* receiver_return = nullptr) {
945 Isolate* const isolate = name->GetIsolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400946
947 int index;
948 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100949 BindingFlags flags;
950 Handle<Object> holder = isolate->context()->Lookup(
951 name, FOLLOW_CHAINS, &index, &attributes, &flags);
952 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400953
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000954 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400955 DCHECK(holder->IsContext());
956 // If the "property" we were looking for is a local variable, the
957 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
958 Handle<Object> receiver = isolate->factory()->undefined_value();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100959 Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400960 // Check for uninitialized bindings.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100961 switch (flags) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400962 case MUTABLE_CHECK_INITIALIZED:
963 case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
964 if (value->IsTheHole()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100965 THROW_NEW_ERROR(isolate,
966 NewReferenceError(MessageTemplate::kNotDefined, name),
967 Object);
968 }
969 // FALLTHROUGH
970 case IMMUTABLE_CHECK_INITIALIZED:
971 if (value->IsTheHole()) {
972 DCHECK(attributes & READ_ONLY);
973 value = isolate->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400974 }
975 // FALLTHROUGH
976 case MUTABLE_IS_INITIALIZED:
977 case IMMUTABLE_IS_INITIALIZED:
978 case IMMUTABLE_IS_INITIALIZED_HARMONY:
979 DCHECK(!value->IsTheHole());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100980 if (receiver_return) *receiver_return = receiver;
981 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400982 case MISSING_BINDING:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100983 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100985 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 }
987
988 // Otherwise, if the slot was found the holder is a context extension
989 // object, subject of a with, or a global object. We read the named
990 // property from it.
991 if (!holder.is_null()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400992 // No need to unhole the value here. This is taken care of by the
993 // GetProperty function.
994 Handle<Object> value;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100995 ASSIGN_RETURN_ON_EXCEPTION(
996 isolate, value, Object::GetProperty(holder, name),
997 Object);
998 if (receiver_return) {
999 *receiver_return =
1000 (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
1001 ? Handle<Object>::cast(isolate->factory()->undefined_value())
1002 : holder;
1003 }
1004 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001005 }
1006
Ben Murdoch097c5b22016-05-18 11:27:45 +01001007 if (should_throw == Object::THROW_ON_ERROR) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001008 // The property doesn't exist - throw exception.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009 THROW_NEW_ERROR(
1010 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001011 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001012
1013 // The property doesn't exist - return undefined.
1014 if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
1015 return isolate->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001016}
1017
Ben Murdoch097c5b22016-05-18 11:27:45 +01001018} // namespace
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001019
1020
Ben Murdoch097c5b22016-05-18 11:27:45 +01001021RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001022 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001023 DCHECK_EQ(1, args.length());
1024 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1025 Handle<Object> value;
1026 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1027 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR));
1028 return *value;
1029}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001030
Ben Murdoch097c5b22016-05-18 11:27:45 +01001031
1032RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
1033 HandleScope scope(isolate);
1034 DCHECK_EQ(1, args.length());
1035 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1036 Handle<Object> value;
1037 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1038 isolate, value, LoadLookupSlot(name, Object::DONT_THROW));
1039 return *value;
1040}
1041
1042
1043RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) {
1044 HandleScope scope(isolate);
1045 DCHECK_EQ(1, args.length());
1046 DCHECK(args[0]->IsString());
1047 Handle<String> name = args.at<String>(0);
1048 Handle<Object> value;
1049 Handle<Object> receiver;
1050 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1051 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver),
1052 MakePair(isolate->heap()->exception(), nullptr));
1053 return MakePair(*value, *receiver);
1054}
1055
1056
1057namespace {
1058
1059MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
1060 LanguageMode language_mode) {
1061 Isolate* const isolate = name->GetIsolate();
1062 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001063
1064 int index;
1065 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001066 BindingFlags flags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001067 Handle<Object> holder =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001068 context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001069 if (holder.is_null()) {
1070 // In case of JSProxy, an exception might have been thrown.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001071 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001073
1074 // The property was found in a context slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075 if (index != Context::kNotFound) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001076 if ((flags == MUTABLE_CHECK_INITIALIZED ||
1077 flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001078 Handle<Context>::cast(holder)->is_the_hole(index)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001079 THROW_NEW_ERROR(isolate,
1080 NewReferenceError(MessageTemplate::kNotDefined, name),
1081 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001083 if ((attributes & READ_ONLY) == 0) {
1084 Handle<Context>::cast(holder)->set(index, *value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 } else if (is_strict(language_mode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001086 // Setting read only property in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001087 THROW_NEW_ERROR(isolate,
1088 NewTypeError(MessageTemplate::kStrictCannotAssign, name),
1089 Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001090 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001091 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001092 }
1093
1094 // Slow case: The property is not in a context slot. It is either in a
1095 // context extension object, a property of the subject of a with, or a
1096 // property of the global object.
1097 Handle<JSReceiver> object;
1098 if (attributes != ABSENT) {
1099 // The property exists on the holder.
1100 object = Handle<JSReceiver>::cast(holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 } else if (is_strict(language_mode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001102 // If absent in strict mode: throw.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001103 THROW_NEW_ERROR(
1104 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001105 } else {
1106 // If absent in sloppy mode: add the property to the global object.
1107 object = Handle<JSReceiver>(context->global_object());
1108 }
1109
Ben Murdoch097c5b22016-05-18 11:27:45 +01001110 ASSIGN_RETURN_ON_EXCEPTION(
1111 isolate, value, Object::SetProperty(object, name, value, language_mode),
1112 Object);
1113 return value;
1114}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001115
Ben Murdoch097c5b22016-05-18 11:27:45 +01001116} // namespace
1117
1118
1119RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) {
1120 HandleScope scope(isolate);
1121 DCHECK_EQ(2, args.length());
1122 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1123 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1124 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1125 StoreLookupSlot(name, value, SLOPPY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001126 return *value;
1127}
1128
1129
Ben Murdoch097c5b22016-05-18 11:27:45 +01001130RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001132 DCHECK_EQ(2, args.length());
1133 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1134 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1135 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1136 StoreLookupSlot(name, value, STRICT));
1137 return *value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138}
1139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140} // namespace internal
1141} // namespace v8