blob: 68df582f13ac0ea3c36cae09ef397a333e5eaec8 [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 Murdochc5610432016-08-08 18:44:38 +010047 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048 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();
Ben Murdochda12d292016-06-02 14:46:10 +0100105 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400106 Handle<String> name(String::cast(pairs->get(i)));
107 Handle<Object> initial_value(pairs->get(i + 1), isolate);
108
109 // We have to declare a global const property. To capture we only
110 // assign to it when evaluating the assignment for "const x =
111 // <expr>" the initial value is the hole.
112 bool is_var = initial_value->IsUndefined();
113 bool is_const = initial_value->IsTheHole();
114 bool is_function = initial_value->IsSharedFunctionInfo();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 DCHECK_EQ(1,
116 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400117
118 Handle<Object> value;
119 if (is_function) {
120 // Copy the function and update its context. Use it as value.
121 Handle<SharedFunctionInfo> shared =
122 Handle<SharedFunctionInfo>::cast(initial_value);
123 Handle<JSFunction> function =
124 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
125 TENURED);
126 value = function;
127 } else {
128 value = isolate->factory()->undefined_value();
129 }
130
131 // Compute the property attributes. According to ECMA-262,
132 // the property must be non-configurable except in eval.
133 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
134 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
135 int attr = NONE;
136 if (is_const) attr |= READ_ONLY;
137 if (is_function && is_native) attr |= READ_ONLY;
138 if (!is_const && !is_eval) attr |= DONT_DELETE;
139
140 Object* result = DeclareGlobals(isolate, global, name, value,
141 static_cast<PropertyAttributes>(attr),
142 is_var, is_const, is_function);
143 if (isolate->has_pending_exception()) return result;
Ben Murdochda12d292016-06-02 14:46:10 +0100144 });
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400145
146 return isolate->heap()->undefined_value();
147}
148
149
150RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
151 HandleScope scope(isolate);
152 // args[0] == name
153 // args[1] == language_mode
154 // args[2] == value (optional)
155
156 // Determine if we need to assign to the variable if it already
157 // exists (based on the number of arguments).
158 RUNTIME_ASSERT(args.length() == 3);
159
160 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 Handle<JSGlobalObject> global(isolate->context()->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 Handle<Object> result;
166 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 isolate, result, Object::SetProperty(global, name, value, language_mode));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 return *result;
169}
170
171
172RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
173 HandleScope handle_scope(isolate);
174 // All constants are declared with an initial value. The name
175 // of the constant is the first argument and the initial value
176 // is the second.
177 RUNTIME_ASSERT(args.length() == 2);
178 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
179 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 Handle<JSGlobalObject> global = isolate->global_object();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400182
183 // Lookup the property as own on the global object.
Ben Murdochc5610432016-08-08 18:44:38 +0100184 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 DCHECK(maybe.IsJust());
187 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400188
189 PropertyAttributes attr =
190 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
191 // Set the value if the property is either missing, or the property attributes
192 // allow setting the value without invoking an accessor.
193 if (it.IsFound()) {
194 // Ignore if we can't reconfigure the value.
195 if ((old_attributes & DONT_DELETE) != 0) {
196 if ((old_attributes & READ_ONLY) != 0 ||
197 it.state() == LookupIterator::ACCESSOR) {
198 return *value;
199 }
200 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
201 }
202 }
203
Ben Murdoch097c5b22016-05-18 11:27:45 +0100204 RETURN_FAILURE_ON_EXCEPTION(
205 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206
207 return *value;
208}
209
210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211namespace {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name,
214 Handle<Object> initial_value,
215 PropertyAttributes attr) {
216 // Declarations are always made in a function, eval or script context, or
217 // a declaration block scope.
218 // In the case of eval code, the context passed is the context of the caller,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 // which may be some nested context and not the declaration context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 Handle<Context> context_arg(isolate->context(), isolate);
221 Handle<Context> context(context_arg->declaration_context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400222
223 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
224 bool is_var = *initial_value == NULL;
225 bool is_const = initial_value->IsTheHole();
226 bool is_function = initial_value->IsJSFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 DCHECK_EQ(1,
228 BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400229
230 int index;
231 PropertyAttributes attributes;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 BindingFlags binding_flags;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233
234 if ((attr & EVAL_DECLARED) != 0) {
235 // Check for a conflict with a lexically scoped variable
236 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
237 &binding_flags);
Ben Murdochc5610432016-08-08 18:44:38 +0100238 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 return ThrowRedeclarationError(isolate, name);
240 }
241 attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
242 }
243
244 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
245 &attributes, &binding_flags);
246 if (holder.is_null()) {
247 // In case of JSProxy, an exception might have been thrown.
248 if (isolate->has_pending_exception()) return isolate->heap()->exception();
249 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250
251 Handle<JSObject> object;
252 Handle<Object> value =
253 is_function ? initial_value
254 : Handle<Object>::cast(isolate->factory()->undefined_value());
255
256 // TODO(verwaest): This case should probably not be covered by this function,
257 // but by DeclareGlobals instead.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 if (attributes != ABSENT && holder->IsJSGlobalObject()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400259 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
260 value, attr, is_var, is_const, is_function);
261 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 if (context_arg->extension()->IsJSGlobalObject()) {
263 Handle<JSGlobalObject> global(
264 JSGlobalObject::cast(context_arg->extension()), isolate);
265 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
266 is_function);
267 } else if (context->IsScriptContext()) {
268 DCHECK(context->global_object()->IsJSGlobalObject());
269 Handle<JSGlobalObject> global(
270 JSGlobalObject::cast(context->global_object()), isolate);
271 return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
272 is_function);
273 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400274
275 if (attributes != ABSENT) {
276 // The name was declared before; check for conflicting re-declarations.
277 if (is_const || (attributes & READ_ONLY) != 0) {
278 return ThrowRedeclarationError(isolate, name);
279 }
280
281 // Skip var re-declarations.
282 if (is_var) return isolate->heap()->undefined_value();
283
284 DCHECK(is_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400286 DCHECK(holder.is_identical_to(context));
287 context->set(index, *initial_value);
288 return isolate->heap()->undefined_value();
289 }
290
291 object = Handle<JSObject>::cast(holder);
292
293 } else if (context->has_extension()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 // Sloppy varblock contexts might not have an extension object yet,
295 // in which case their extension is a ScopeInfo.
296 if (context->extension()->IsScopeInfo()) {
297 DCHECK(context->IsBlockContext());
298 object = isolate->factory()->NewJSObject(
299 isolate->context_extension_function());
300 Handle<HeapObject> extension =
301 isolate->factory()->NewSloppyBlockWithEvalContextExtension(
302 handle(context->scope_info()), object);
303 context->set_extension(*extension);
304 } else {
305 object = handle(context->extension_object(), isolate);
306 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400307 DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
308 } else {
309 DCHECK(context->IsFunctionContext());
310 object =
311 isolate->factory()->NewJSObject(isolate->context_extension_function());
312 context->set_extension(*object);
313 }
314
315 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
316 object, name, value, attr));
317
318 return isolate->heap()->undefined_value();
319}
320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321} // namespace
322
323
324RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
325 HandleScope scope(isolate);
326 DCHECK_EQ(3, args.length());
327 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
328 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1);
329 CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2);
330
331 PropertyAttributes attributes =
332 static_cast<PropertyAttributes>(property_attributes->value());
333 return DeclareLookupSlot(isolate, name, initial_value, attributes);
334}
335
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400336
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337namespace {
338
339// Find the arguments of the JavaScript function invocation that called
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340// into C++ code. Collect these in a newly allocated array of handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000342 int* total_argc) {
343 // Find frame containing arguments passed to the caller.
344 JavaScriptFrameIterator it(isolate);
345 JavaScriptFrame* frame = it.frame();
346 List<JSFunction*> functions(2);
347 frame->GetFunctions(&functions);
348 if (functions.length() > 1) {
349 int inlined_jsframe_index = functions.length() - 1;
350 TranslatedState translated_values(frame);
351 translated_values.Prepare(false, frame->fp());
352
353 int argument_count = 0;
354 TranslatedFrame* translated_frame =
355 translated_values.GetArgumentsInfoFromJSFrameIndex(
356 inlined_jsframe_index, &argument_count);
357 TranslatedFrame::iterator iter = translated_frame->begin();
358
359 // Skip the function.
360 iter++;
361
362 // Skip the receiver.
363 iter++;
364 argument_count--;
365
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366 *total_argc = argument_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 base::SmartArrayPointer<Handle<Object>> param_data(
368 NewArray<Handle<Object>>(*total_argc));
369 bool should_deoptimize = false;
370 for (int i = 0; i < argument_count; i++) {
371 should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
372 Handle<Object> value = iter->GetValue();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100373 param_data[i] = value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 iter++;
375 }
376
377 if (should_deoptimize) {
378 translated_values.StoreMaterializedValuesAndDeopt();
379 }
380
381 return param_data;
382 } else {
383 it.AdvanceToArgumentsFrame();
384 frame = it.frame();
385 int args_count = frame->ComputeParametersCount();
386
Ben Murdoch097c5b22016-05-18 11:27:45 +0100387 *total_argc = args_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 base::SmartArrayPointer<Handle<Object>> param_data(
389 NewArray<Handle<Object>>(*total_argc));
390 for (int i = 0; i < args_count; i++) {
391 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100392 param_data[i] = val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 }
394 return param_data;
395 }
396}
397
398
399template <typename T>
400Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
401 T parameters, int argument_count) {
402 CHECK(!IsSubclassConstructor(callee->shared()->kind()));
403 DCHECK(callee->shared()->has_simple_parameters());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400404 Handle<JSObject> result =
405 isolate->factory()->NewArgumentsObject(callee, argument_count);
406
407 // Allocate the elements if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 int parameter_count = callee->shared()->internal_formal_parameter_count();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400409 if (argument_count > 0) {
410 if (parameter_count > 0) {
411 int mapped_count = Min(argument_count, parameter_count);
412 Handle<FixedArray> parameter_map =
413 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
414 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 result->set_map(isolate->native_context()->fast_aliased_arguments_map());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400416 result->set_elements(*parameter_map);
417
418 // Store the context and the arguments array at the beginning of the
419 // parameter map.
420 Handle<Context> context(isolate->context());
421 Handle<FixedArray> arguments =
422 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
423 parameter_map->set(0, *context);
424 parameter_map->set(1, *arguments);
425
426 // Loop over the actual parameters backwards.
427 int index = argument_count - 1;
428 while (index >= mapped_count) {
429 // These go directly in the arguments array and have no
430 // corresponding slot in the parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400432 --index;
433 }
434
435 Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
436 while (index >= 0) {
437 // Detect duplicate names to the right in the parameter list.
438 Handle<String> name(scope_info->ParameterName(index));
439 int context_local_count = scope_info->ContextLocalCount();
440 bool duplicate = false;
441 for (int j = index + 1; j < parameter_count; ++j) {
442 if (scope_info->ParameterName(j) == *name) {
443 duplicate = true;
444 break;
445 }
446 }
447
448 if (duplicate) {
449 // This goes directly in the arguments array with a hole in the
450 // parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400452 parameter_map->set_the_hole(index + 2);
453 } else {
454 // The context index goes in the parameter map with a hole in the
455 // arguments array.
456 int context_index = -1;
457 for (int j = 0; j < context_local_count; ++j) {
458 if (scope_info->ContextLocalName(j) == *name) {
459 context_index = j;
460 break;
461 }
462 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400464 DCHECK(context_index >= 0);
465 arguments->set_the_hole(index);
466 parameter_map->set(
467 index + 2,
468 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
469 }
470
471 --index;
472 }
473 } else {
474 // If there is no aliasing, the arguments object elements are not
475 // special in any way.
476 Handle<FixedArray> elements =
477 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
478 result->set_elements(*elements);
479 for (int i = 0; i < argument_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 elements->set(i, parameters[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400481 }
482 }
483 }
484 return result;
485}
486
487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488class HandleArguments BASE_EMBEDDED {
489 public:
490 explicit HandleArguments(Handle<Object>* array) : array_(array) {}
491 Object* operator[](int index) { return *array_[index]; }
492
493 private:
494 Handle<Object>* array_;
495};
496
497
498class ParameterArguments BASE_EMBEDDED {
499 public:
500 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
501 Object*& operator[](int index) { return *(parameters_ - index - 1); }
502
503 private:
504 Object** parameters_;
505};
506
507} // namespace
508
509
510RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400511 HandleScope scope(isolate);
512 DCHECK(args.length() == 1);
513 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 // This generic runtime function can also be used when the caller has been
515 // inlined, we use the slow but accurate {GetCallerArguments}.
516 int argument_count = 0;
517 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100518 GetCallerArguments(isolate, &argument_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 HandleArguments argument_getter(arguments.get());
520 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
521}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400522
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400523
Ben Murdoch097c5b22016-05-18 11:27:45 +0100524RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100526 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
528 // This generic runtime function can also be used when the caller has been
529 // inlined, we use the slow but accurate {GetCallerArguments}.
530 int argument_count = 0;
531 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100532 GetCallerArguments(isolate, &argument_count);
533 Handle<JSObject> result =
534 isolate->factory()->NewArgumentsObject(callee, argument_count);
535 if (argument_count) {
536 Handle<FixedArray> array =
537 isolate->factory()->NewUninitializedFixedArray(argument_count);
538 DisallowHeapAllocation no_gc;
539 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
540 for (int i = 0; i < argument_count; i++) {
541 array->set(i, *arguments[i], mode);
542 }
543 result->set_elements(*array);
544 }
545 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546}
547
548
Ben Murdoch097c5b22016-05-18 11:27:45 +0100549RUNTIME_FUNCTION(Runtime_NewRestParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100551 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100553 int start_index = callee->shared()->internal_formal_parameter_count();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 // This generic runtime function can also be used when the caller has been
555 // inlined, we use the slow but accurate {GetCallerArguments}.
556 int argument_count = 0;
557 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100558 GetCallerArguments(isolate, &argument_count);
559 int num_elements = std::max(0, argument_count - start_index);
Ben Murdochda12d292016-06-02 14:46:10 +0100560 Handle<JSObject> result =
561 isolate->factory()->NewJSArray(FAST_ELEMENTS, num_elements, num_elements,
562 DONT_INITIALIZE_ARRAY_ELEMENTS);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100563 {
564 DisallowHeapAllocation no_gc;
565 FixedArray* elements = FixedArray::cast(result->elements());
Ben Murdochc5610432016-08-08 18:44:38 +0100566 WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100567 for (int i = 0; i < num_elements; i++) {
568 elements->set(i, *arguments[i + start_index], mode);
569 }
570 }
571 return *result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400572}
573
574
575RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
576 HandleScope scope(isolate);
577 DCHECK(args.length() == 3);
578 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
579 Object** parameters = reinterpret_cast<Object**>(args[1]);
580 CONVERT_SMI_ARG_CHECKED(argument_count, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 ParameterArguments argument_getter(parameters);
582 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400583}
584
585
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400586RUNTIME_FUNCTION(Runtime_NewClosure) {
587 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 DCHECK_EQ(1, args.length());
589 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
590 Handle<Context> context(isolate->context(), isolate);
591 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
592 NOT_TENURED);
593}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595
596RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
597 HandleScope scope(isolate);
598 DCHECK_EQ(1, args.length());
599 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
600 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400601 // The caller ensures that we pretenure closures that are assigned
602 // directly to properties.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400603 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 TENURED);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400605}
606
607static Object* FindNameClash(Handle<ScopeInfo> scope_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000608 Handle<JSGlobalObject> global_object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400609 Handle<ScriptContextTable> script_context) {
610 Isolate* isolate = scope_info->GetIsolate();
611 for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
612 Handle<String> name(scope_info->ContextLocalName(var));
613 VariableMode mode = scope_info->ContextLocalMode(var);
614 ScriptContextTable::LookupResult lookup;
615 if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
616 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
617 return ThrowRedeclarationError(isolate, name);
618 }
619 }
620
621 if (IsLexicalVariableMode(mode)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100622 LookupIterator it(global_object, name, global_object,
Ben Murdochc5610432016-08-08 18:44:38 +0100623 LookupIterator::OWN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400624 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625 if (!maybe.IsJust()) return isolate->heap()->exception();
626 if ((maybe.FromJust() & DONT_DELETE) != 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400627 return ThrowRedeclarationError(isolate, name);
628 }
629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 JSGlobalObject::InvalidatePropertyCell(global_object, name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400631 }
632 }
633 return isolate->heap()->undefined_value();
634}
635
636
637RUNTIME_FUNCTION(Runtime_NewScriptContext) {
638 HandleScope scope(isolate);
639 DCHECK(args.length() == 2);
640
641 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
642 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000643 Handle<JSGlobalObject> global_object(function->context()->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400644 Handle<Context> native_context(global_object->native_context());
645 Handle<ScriptContextTable> script_context_table(
646 native_context->script_context_table());
647
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400648 Object* name_clash_result =
649 FindNameClash(scope_info, global_object, script_context_table);
650 if (isolate->has_pending_exception()) return name_clash_result;
651
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 // Script contexts have a canonical empty function as their closure, not the
653 // anonymous closure containing the global code. See
654 // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
655 Handle<JSFunction> closure(
656 function->shared()->IsBuiltin() ? *function : native_context->closure());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400657 Handle<Context> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 isolate->factory()->NewScriptContext(closure, scope_info);
659
660 result->InitializeGlobalSlots();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400661
662 DCHECK(function->context() == isolate->context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663 DCHECK(*global_object == result->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400664
665 Handle<ScriptContextTable> new_script_context_table =
666 ScriptContextTable::Extend(script_context_table, result);
667 native_context->set_script_context_table(*new_script_context_table);
668 return *result;
669}
670
671
672RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
673 HandleScope scope(isolate);
674 DCHECK(args.length() == 1);
675
676 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
677
678 DCHECK(function->context() == isolate->context());
679 int length = function->shared()->scope_info()->ContextLength();
680 return *isolate->factory()->NewFunctionContext(length, function);
681}
682
683
684RUNTIME_FUNCTION(Runtime_PushWithContext) {
685 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 DCHECK_EQ(2, args.length());
687 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
688 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400689 Handle<Context> current(isolate->context());
690 Handle<Context> context =
691 isolate->factory()->NewWithContext(function, current, extension_object);
692 isolate->set_context(*context);
693 return *context;
694}
695
696
697RUNTIME_FUNCTION(Runtime_PushCatchContext) {
698 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 DCHECK_EQ(3, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400700 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
701 CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 Handle<Context> current(isolate->context());
704 Handle<Context> context = isolate->factory()->NewCatchContext(
705 function, current, name, thrown_object);
706 isolate->set_context(*context);
707 return *context;
708}
709
710
711RUNTIME_FUNCTION(Runtime_PushBlockContext) {
712 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 DCHECK_EQ(2, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400714 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000715 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400716 Handle<Context> current(isolate->context());
717 Handle<Context> context =
718 isolate->factory()->NewBlockContext(function, current, scope_info);
719 isolate->set_context(*context);
720 return *context;
721}
722
723
724RUNTIME_FUNCTION(Runtime_IsJSModule) {
725 SealHandleScope shs(isolate);
726 DCHECK(args.length() == 1);
727 CONVERT_ARG_CHECKED(Object, obj, 0);
728 return isolate->heap()->ToBoolean(obj->IsJSModule());
729}
730
731
732RUNTIME_FUNCTION(Runtime_PushModuleContext) {
733 SealHandleScope shs(isolate);
734 DCHECK(args.length() == 2);
735 CONVERT_SMI_ARG_CHECKED(index, 0);
736
737 if (!args[1]->IsScopeInfo()) {
738 // Module already initialized. Find hosting context and retrieve context.
739 Context* host = Context::cast(isolate->context())->script_context();
740 Context* context = Context::cast(host->get(index));
741 DCHECK(context->previous() == isolate->context());
742 isolate->set_context(context);
743 return context;
744 }
745
746 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
747
748 // Allocate module context.
749 HandleScope scope(isolate);
750 Factory* factory = isolate->factory();
751 Handle<Context> context = factory->NewModuleContext(scope_info);
752 Handle<JSModule> module = factory->NewJSModule(context, scope_info);
753 context->set_module(*module);
754 Context* previous = isolate->context();
755 context->set_previous(previous);
756 context->set_closure(previous->closure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 context->set_native_context(previous->native_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400758 isolate->set_context(*context);
759
760 // Find hosting scope and initialize internal variable holding module there.
761 previous->script_context()->set(index, *context);
762
763 return *context;
764}
765
766
767RUNTIME_FUNCTION(Runtime_DeclareModules) {
768 HandleScope scope(isolate);
769 DCHECK(args.length() == 1);
770 CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
771 Context* host_context = isolate->context();
772
773 for (int i = 0; i < descriptions->length(); ++i) {
774 Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
775 int host_index = description->host_index();
776 Handle<Context> context(Context::cast(host_context->get(host_index)));
777 Handle<JSModule> module(context->module());
778
779 for (int j = 0; j < description->length(); ++j) {
780 Handle<String> name(description->name(j));
781 VariableMode mode = description->mode(j);
782 int index = description->index(j);
783 switch (mode) {
784 case VAR:
785 case LET:
786 case CONST:
Ben Murdochc5610432016-08-08 18:44:38 +0100787 case CONST_LEGACY: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400788 PropertyAttributes attr =
789 IsImmutableVariableMode(mode) ? FROZEN : SEALED;
790 Handle<AccessorInfo> info =
791 Accessors::MakeModuleExport(name, index, attr);
792 Handle<Object> result =
793 JSObject::SetAccessor(module, info).ToHandleChecked();
794 DCHECK(!result->IsUndefined());
795 USE(result);
796 break;
797 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400798 case TEMPORARY:
799 case DYNAMIC:
800 case DYNAMIC_GLOBAL:
801 case DYNAMIC_LOCAL:
802 UNREACHABLE();
803 }
804 }
805
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR)
807 .IsNothing()) {
808 DCHECK(false);
809 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400810 }
811
812 DCHECK(!isolate->has_pending_exception());
813 return isolate->heap()->undefined_value();
814}
815
816
817RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
818 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100819 DCHECK_EQ(1, args.length());
820 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400821
822 int index;
823 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100824 BindingFlags flags;
825 Handle<Object> holder = isolate->context()->Lookup(
826 name, FOLLOW_CHAINS, &index, &attributes, &flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400827
828 // If the slot was not found the result is true.
829 if (holder.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 // In case of JSProxy, an exception might have been thrown.
831 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400832 return isolate->heap()->true_value();
833 }
834
835 // If the slot was found in a context, it should be DONT_DELETE.
836 if (holder->IsContext()) {
837 return isolate->heap()->false_value();
838 }
839
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 // The slot was found in a JSReceiver, either a context extension object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400841 // the global object, or the subject of a with. Try to delete it
842 // (respecting DONT_DELETE).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000843 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
844 Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
845 MAYBE_RETURN(result, isolate->heap()->exception());
846 return isolate->heap()->ToBoolean(result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400847}
848
849
Ben Murdoch097c5b22016-05-18 11:27:45 +0100850namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851
Ben Murdoch097c5b22016-05-18 11:27:45 +0100852MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
853 Object::ShouldThrow should_throw,
854 Handle<Object>* receiver_return = nullptr) {
855 Isolate* const isolate = name->GetIsolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400856
857 int index;
858 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100859 BindingFlags flags;
860 Handle<Object> holder = isolate->context()->Lookup(
861 name, FOLLOW_CHAINS, &index, &attributes, &flags);
862 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400863
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000864 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400865 DCHECK(holder->IsContext());
866 // If the "property" we were looking for is a local variable, the
867 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
868 Handle<Object> receiver = isolate->factory()->undefined_value();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100869 Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400870 // Check for uninitialized bindings.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100871 switch (flags) {
Ben Murdochc5610432016-08-08 18:44:38 +0100872 case BINDING_CHECK_INITIALIZED:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400873 if (value->IsTheHole()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874 THROW_NEW_ERROR(isolate,
875 NewReferenceError(MessageTemplate::kNotDefined, name),
876 Object);
877 }
878 // FALLTHROUGH
Ben Murdochc5610432016-08-08 18:44:38 +0100879 case BINDING_IS_INITIALIZED:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400880 DCHECK(!value->IsTheHole());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100881 if (receiver_return) *receiver_return = receiver;
882 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400883 case MISSING_BINDING:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100884 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400885 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100886 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400887 }
888
889 // Otherwise, if the slot was found the holder is a context extension
890 // object, subject of a with, or a global object. We read the named
891 // property from it.
892 if (!holder.is_null()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400893 // No need to unhole the value here. This is taken care of by the
894 // GetProperty function.
895 Handle<Object> value;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100896 ASSIGN_RETURN_ON_EXCEPTION(
897 isolate, value, Object::GetProperty(holder, name),
898 Object);
899 if (receiver_return) {
900 *receiver_return =
901 (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
902 ? Handle<Object>::cast(isolate->factory()->undefined_value())
903 : holder;
904 }
905 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400906 }
907
Ben Murdoch097c5b22016-05-18 11:27:45 +0100908 if (should_throw == Object::THROW_ON_ERROR) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400909 // The property doesn't exist - throw exception.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100910 THROW_NEW_ERROR(
911 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400912 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100913
914 // The property doesn't exist - return undefined.
915 if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
916 return isolate->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400917}
918
Ben Murdoch097c5b22016-05-18 11:27:45 +0100919} // namespace
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400920
921
Ben Murdoch097c5b22016-05-18 11:27:45 +0100922RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400923 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100924 DCHECK_EQ(1, args.length());
925 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
926 Handle<Object> value;
927 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
928 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR));
929 return *value;
930}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400931
Ben Murdoch097c5b22016-05-18 11:27:45 +0100932
933RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
934 HandleScope scope(isolate);
935 DCHECK_EQ(1, args.length());
936 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
937 Handle<Object> value;
938 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
939 isolate, value, LoadLookupSlot(name, Object::DONT_THROW));
940 return *value;
941}
942
943
944RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) {
945 HandleScope scope(isolate);
946 DCHECK_EQ(1, args.length());
947 DCHECK(args[0]->IsString());
948 Handle<String> name = args.at<String>(0);
949 Handle<Object> value;
950 Handle<Object> receiver;
951 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
952 isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver),
953 MakePair(isolate->heap()->exception(), nullptr));
954 return MakePair(*value, *receiver);
955}
956
957
958namespace {
959
960MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
961 LanguageMode language_mode) {
962 Isolate* const isolate = name->GetIsolate();
963 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400964
965 int index;
966 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100967 BindingFlags flags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400968 Handle<Object> holder =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100969 context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 if (holder.is_null()) {
971 // In case of JSProxy, an exception might have been thrown.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100972 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400974
975 // The property was found in a context slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 if (index != Context::kNotFound) {
Ben Murdochc5610432016-08-08 18:44:38 +0100977 if (flags == BINDING_CHECK_INITIALIZED &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000978 Handle<Context>::cast(holder)->is_the_hole(index)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100979 THROW_NEW_ERROR(isolate,
980 NewReferenceError(MessageTemplate::kNotDefined, name),
981 Object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400983 if ((attributes & READ_ONLY) == 0) {
984 Handle<Context>::cast(holder)->set(index, *value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000985 } else if (is_strict(language_mode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 // Setting read only property in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100987 THROW_NEW_ERROR(isolate,
988 NewTypeError(MessageTemplate::kStrictCannotAssign, name),
989 Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400990 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100991 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400992 }
993
994 // Slow case: The property is not in a context slot. It is either in a
995 // context extension object, a property of the subject of a with, or a
996 // property of the global object.
997 Handle<JSReceiver> object;
998 if (attributes != ABSENT) {
999 // The property exists on the holder.
1000 object = Handle<JSReceiver>::cast(holder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 } else if (is_strict(language_mode)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001002 // If absent in strict mode: throw.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001003 THROW_NEW_ERROR(
1004 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001005 } else {
1006 // If absent in sloppy mode: add the property to the global object.
1007 object = Handle<JSReceiver>(context->global_object());
1008 }
1009
Ben Murdoch097c5b22016-05-18 11:27:45 +01001010 ASSIGN_RETURN_ON_EXCEPTION(
1011 isolate, value, Object::SetProperty(object, name, value, language_mode),
1012 Object);
1013 return value;
1014}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001015
Ben Murdoch097c5b22016-05-18 11:27:45 +01001016} // namespace
1017
1018
1019RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) {
1020 HandleScope scope(isolate);
1021 DCHECK_EQ(2, args.length());
1022 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1023 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1024 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1025 StoreLookupSlot(name, value, SLOPPY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001026 return *value;
1027}
1028
1029
Ben Murdoch097c5b22016-05-18 11:27:45 +01001030RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001031 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001032 DCHECK_EQ(2, args.length());
1033 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1034 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
1035 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
1036 StoreLookupSlot(name, value, STRICT));
1037 return *value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001038}
1039
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001040} // namespace internal
1041} // namespace v8