blob: 0bdbe2e44172da6f9a0efd3bac703ba0aafc8a5e [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
Ben Murdoch61f157c2016-09-16 13:49:30 +010019enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 };
20
21static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name,
22 RedeclarationType redeclaration_type) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040023 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010024 if (redeclaration_type == RedeclarationType::kSyntaxError) {
25 THROW_NEW_ERROR_RETURN_FAILURE(
26 isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name));
27 } else {
28 THROW_NEW_ERROR_RETURN_FAILURE(
29 isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
30 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031}
32
33
34RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
35 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 THROW_NEW_ERROR_RETURN_FAILURE(isolate,
37 NewTypeError(MessageTemplate::kConstAssign));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038}
39
40
41// May throw a RedeclarationError.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 Handle<String> name, Handle<Object> value,
44 PropertyAttributes attr, bool is_var,
Ben Murdoch61f157c2016-09-16 13:49:30 +010045 bool is_function,
46 RedeclarationType redeclaration_type) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040047 Handle<ScriptContextTable> script_contexts(
48 global->native_context()->script_context_table());
49 ScriptContextTable::LookupResult lookup;
50 if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
51 IsLexicalVariableMode(lookup.mode)) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010052 // ES#sec-globaldeclarationinstantiation 6.a:
53 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
54 // exception.
55 return ThrowRedeclarationError(isolate, name,
56 RedeclarationType::kSyntaxError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040057 }
58
59 // Do the lookup own properties only, see ES5 erratum.
Ben Murdochc5610432016-08-08 18:44:38 +010060 LookupIterator it(global, name, global, LookupIterator::OWN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 if (!maybe.IsJust()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063
64 if (it.IsFound()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 PropertyAttributes old_attributes = maybe.FromJust();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040066 // The name was declared before; check for conflicting re-declarations.
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067
68 // Skip var re-declarations.
69 if (is_var) return isolate->heap()->undefined_value();
70
71 DCHECK(is_function);
72 if ((old_attributes & DONT_DELETE) != 0) {
73 // Only allow reconfiguring globals to functions in user code (no
74 // natives, which are marked as read-only).
75 DCHECK((attr & READ_ONLY) == 0);
76
77 // Check whether we can reconfigure the existing property into a
78 // function.
79 PropertyDetails old_details = it.property_details();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040080 if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
Ben Murdoch097c5b22016-05-18 11:27:45 +010081 (it.state() == LookupIterator::ACCESSOR &&
82 it.GetAccessors()->IsAccessorPair())) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010083 // ES#sec-globaldeclarationinstantiation 5.d:
84 // If hasRestrictedGlobal is true, throw a SyntaxError exception.
85 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
86 // If fnDefinable is false, throw a TypeError exception.
87 return ThrowRedeclarationError(isolate, name, redeclaration_type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040088 }
89 // If the existing property is not configurable, keep its attributes. Do
90 attr = old_attributes;
91 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010092
93 // If the current state is ACCESSOR, this could mean it's an AccessorInfo
94 // type property. We are not allowed to call into such setters during global
95 // function declaration since this would break e.g., onload. Meaning
96 // 'function onload() {}' would invalidly register that function as the
97 // onload callback. To avoid this situation, we first delete the property
98 // before readding it as a regular data property below.
99 if (it.state() == LookupIterator::ACCESSOR) it.Delete();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400100 }
101
102 // Define or redefine own property.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100103 RETURN_FAILURE_ON_EXCEPTION(
104 isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400105
106 return isolate->heap()->undefined_value();
107}
108
109
110RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
111 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 DCHECK_EQ(2, args.length());
113 Handle<JSGlobalObject> global(isolate->global_object());
114 Handle<Context> context(isolate->context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
117 CONVERT_SMI_ARG_CHECKED(flags, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400118
119 // Traverse the name/value pairs and set the properties.
120 int length = pairs->length();
Ben Murdochda12d292016-06-02 14:46:10 +0100121 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122 Handle<String> name(String::cast(pairs->get(i)));
123 Handle<Object> initial_value(pairs->get(i + 1), isolate);
124
Ben Murdoch61f157c2016-09-16 13:49:30 +0100125 bool is_var = initial_value->IsUndefined(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 bool is_function = initial_value->IsSharedFunctionInfo();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100127 DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400128
129 Handle<Object> value;
130 if (is_function) {
131 // Copy the function and update its context. Use it as value.
132 Handle<SharedFunctionInfo> shared =
133 Handle<SharedFunctionInfo>::cast(initial_value);
134 Handle<JSFunction> function =
135 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
136 TENURED);
137 value = function;
138 } else {
139 value = isolate->factory()->undefined_value();
140 }
141
142 // Compute the property attributes. According to ECMA-262,
143 // the property must be non-configurable except in eval.
144 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
145 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
146 int attr = NONE;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147 if (is_function && is_native) attr |= READ_ONLY;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100148 if (!is_eval) attr |= DONT_DELETE;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400149
Ben Murdoch61f157c2016-09-16 13:49:30 +0100150 // ES#sec-globaldeclarationinstantiation 5.d:
151 // If hasRestrictedGlobal is true, throw a SyntaxError exception.
152 Object* result = DeclareGlobals(
153 isolate, global, name, value, static_cast<PropertyAttributes>(attr),
154 is_var, is_function, RedeclarationType::kSyntaxError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155 if (isolate->has_pending_exception()) return result;
Ben Murdochda12d292016-06-02 14:46:10 +0100156 });
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400157
158 return isolate->heap()->undefined_value();
159}
160
161
162RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
163 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100164 DCHECK_EQ(3, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400167 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 Handle<JSGlobalObject> global(isolate->context()->global_object());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100170 RETURN_RESULT_OR_FAILURE(
171 isolate, Object::SetProperty(global, name, value, language_mode));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400172}
173
174
175RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
176 HandleScope handle_scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100177 DCHECK_EQ(2, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210namespace {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211
Ben Murdoch61f157c2016-09-16 13:49:30 +0100212Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name,
213 Handle<Object> value) {
214 // Declarations are always made in a function, native, or script context, or
215 // a declaration block scope. Since this is called from eval, the context
216 // passed is the context of the caller, which may be some nested context and
217 // not the declaration context.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 Handle<Context> context_arg(isolate->context(), isolate);
219 Handle<Context> context(context_arg->declaration_context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220
Ben Murdoch61f157c2016-09-16 13:49:30 +0100221 DCHECK(context->IsFunctionContext() || context->IsNativeContext() ||
222 context->IsScriptContext() ||
223 (context->IsBlockContext() && context->has_extension()));
224
225 bool is_function = value->IsJSFunction();
226 bool is_var = !is_function;
227 DCHECK(!is_var || value->IsUndefined(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400228
229 int index;
230 PropertyAttributes attributes;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231 BindingFlags binding_flags;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232
Ben Murdoch61f157c2016-09-16 13:49:30 +0100233 // Check for a conflict with a lexically scoped variable
234 context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &binding_flags);
235 if (attributes != ABSENT && binding_flags == BINDING_CHECK_INITIALIZED) {
236 // ES#sec-evaldeclarationinstantiation 5.a.i.1:
237 // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
238 // exception.
239 // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
240 // Throw a SyntaxError exception.
241 return ThrowRedeclarationError(isolate, name,
242 RedeclarationType::kSyntaxError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 }
244
245 Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
246 &attributes, &binding_flags);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100247 DCHECK(!isolate->has_pending_exception());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400248
249 Handle<JSObject> object;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400250
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 if (attributes != ABSENT && holder->IsJSGlobalObject()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100252 // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
253 // If fnDefinable is false, throw a TypeError exception.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400254 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100255 value, NONE, is_var, is_function,
256 RedeclarationType::kTypeError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400257 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 if (context_arg->extension()->IsJSGlobalObject()) {
259 Handle<JSGlobalObject> global(
260 JSGlobalObject::cast(context_arg->extension()), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100261 return DeclareGlobals(isolate, global, name, value, NONE, is_var,
262 is_function, RedeclarationType::kTypeError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000263 } else if (context->IsScriptContext()) {
264 DCHECK(context->global_object()->IsJSGlobalObject());
265 Handle<JSGlobalObject> global(
266 JSGlobalObject::cast(context->global_object()), isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100267 return DeclareGlobals(isolate, global, name, value, NONE, is_var,
268 is_function, RedeclarationType::kTypeError);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400270
271 if (attributes != ABSENT) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100272 DCHECK_EQ(NONE, attributes);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273
274 // Skip var re-declarations.
275 if (is_var) return isolate->heap()->undefined_value();
276
277 DCHECK(is_function);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279 DCHECK(holder.is_identical_to(context));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100280 context->set(index, *value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400281 return isolate->heap()->undefined_value();
282 }
283
284 object = Handle<JSObject>::cast(holder);
285
286 } else if (context->has_extension()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287 // Sloppy varblock contexts might not have an extension object yet,
288 // in which case their extension is a ScopeInfo.
289 if (context->extension()->IsScopeInfo()) {
290 DCHECK(context->IsBlockContext());
291 object = isolate->factory()->NewJSObject(
292 isolate->context_extension_function());
293 Handle<HeapObject> extension =
294 isolate->factory()->NewSloppyBlockWithEvalContextExtension(
295 handle(context->scope_info()), object);
296 context->set_extension(*extension);
297 } else {
298 object = handle(context->extension_object(), isolate);
299 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400300 DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
301 } else {
302 DCHECK(context->IsFunctionContext());
303 object =
304 isolate->factory()->NewJSObject(isolate->context_extension_function());
305 context->set_extension(*object);
306 }
307
308 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
Ben Murdoch61f157c2016-09-16 13:49:30 +0100309 object, name, value, NONE));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400310
311 return isolate->heap()->undefined_value();
312}
313
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314} // namespace
315
Ben Murdoch61f157c2016-09-16 13:49:30 +0100316RUNTIME_FUNCTION(Runtime_DeclareEvalFunction) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 HandleScope scope(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100318 DCHECK_EQ(2, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100320 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
321 return DeclareEvalHelper(isolate, name, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322}
323
Ben Murdoch61f157c2016-09-16 13:49:30 +0100324RUNTIME_FUNCTION(Runtime_DeclareEvalVar) {
325 HandleScope scope(isolate);
326 DCHECK_EQ(1, args.length());
327 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
328 return DeclareEvalHelper(isolate, name,
329 isolate->factory()->undefined_value());
330}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400331
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332namespace {
333
334// Find the arguments of the JavaScript function invocation that called
Ben Murdoch097c5b22016-05-18 11:27:45 +0100335// into C++ code. Collect these in a newly allocated array of handles.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000337 int* total_argc) {
338 // Find frame containing arguments passed to the caller.
339 JavaScriptFrameIterator it(isolate);
340 JavaScriptFrame* frame = it.frame();
341 List<JSFunction*> functions(2);
342 frame->GetFunctions(&functions);
343 if (functions.length() > 1) {
344 int inlined_jsframe_index = functions.length() - 1;
345 TranslatedState translated_values(frame);
346 translated_values.Prepare(false, frame->fp());
347
348 int argument_count = 0;
349 TranslatedFrame* translated_frame =
350 translated_values.GetArgumentsInfoFromJSFrameIndex(
351 inlined_jsframe_index, &argument_count);
352 TranslatedFrame::iterator iter = translated_frame->begin();
353
354 // Skip the function.
355 iter++;
356
357 // Skip the receiver.
358 iter++;
359 argument_count--;
360
Ben Murdoch097c5b22016-05-18 11:27:45 +0100361 *total_argc = argument_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 base::SmartArrayPointer<Handle<Object>> param_data(
363 NewArray<Handle<Object>>(*total_argc));
364 bool should_deoptimize = false;
365 for (int i = 0; i < argument_count; i++) {
366 should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
367 Handle<Object> value = iter->GetValue();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100368 param_data[i] = value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369 iter++;
370 }
371
372 if (should_deoptimize) {
373 translated_values.StoreMaterializedValuesAndDeopt();
374 }
375
376 return param_data;
377 } else {
378 it.AdvanceToArgumentsFrame();
379 frame = it.frame();
380 int args_count = frame->ComputeParametersCount();
381
Ben Murdoch097c5b22016-05-18 11:27:45 +0100382 *total_argc = args_count;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 base::SmartArrayPointer<Handle<Object>> param_data(
384 NewArray<Handle<Object>>(*total_argc));
385 for (int i = 0; i < args_count; i++) {
386 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100387 param_data[i] = val;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 }
389 return param_data;
390 }
391}
392
393
394template <typename T>
395Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
396 T parameters, int argument_count) {
397 CHECK(!IsSubclassConstructor(callee->shared()->kind()));
398 DCHECK(callee->shared()->has_simple_parameters());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400399 Handle<JSObject> result =
400 isolate->factory()->NewArgumentsObject(callee, argument_count);
401
402 // Allocate the elements if needed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000403 int parameter_count = callee->shared()->internal_formal_parameter_count();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400404 if (argument_count > 0) {
405 if (parameter_count > 0) {
406 int mapped_count = Min(argument_count, parameter_count);
407 Handle<FixedArray> parameter_map =
408 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
409 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 result->set_map(isolate->native_context()->fast_aliased_arguments_map());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400411 result->set_elements(*parameter_map);
412
413 // Store the context and the arguments array at the beginning of the
414 // parameter map.
415 Handle<Context> context(isolate->context());
416 Handle<FixedArray> arguments =
417 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
418 parameter_map->set(0, *context);
419 parameter_map->set(1, *arguments);
420
421 // Loop over the actual parameters backwards.
422 int index = argument_count - 1;
423 while (index >= mapped_count) {
424 // These go directly in the arguments array and have no
425 // corresponding slot in the parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400427 --index;
428 }
429
430 Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
431 while (index >= 0) {
432 // Detect duplicate names to the right in the parameter list.
433 Handle<String> name(scope_info->ParameterName(index));
434 int context_local_count = scope_info->ContextLocalCount();
435 bool duplicate = false;
436 for (int j = index + 1; j < parameter_count; ++j) {
437 if (scope_info->ParameterName(j) == *name) {
438 duplicate = true;
439 break;
440 }
441 }
442
443 if (duplicate) {
444 // This goes directly in the arguments array with a hole in the
445 // parameter map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 arguments->set(index, parameters[index]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400447 parameter_map->set_the_hole(index + 2);
448 } else {
449 // The context index goes in the parameter map with a hole in the
450 // arguments array.
451 int context_index = -1;
452 for (int j = 0; j < context_local_count; ++j) {
453 if (scope_info->ContextLocalName(j) == *name) {
454 context_index = j;
455 break;
456 }
457 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 DCHECK(context_index >= 0);
460 arguments->set_the_hole(index);
461 parameter_map->set(
462 index + 2,
463 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
464 }
465
466 --index;
467 }
468 } else {
469 // If there is no aliasing, the arguments object elements are not
470 // special in any way.
471 Handle<FixedArray> elements =
472 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
473 result->set_elements(*elements);
474 for (int i = 0; i < argument_count; ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 elements->set(i, parameters[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400476 }
477 }
478 }
479 return result;
480}
481
482
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483class HandleArguments BASE_EMBEDDED {
484 public:
485 explicit HandleArguments(Handle<Object>* array) : array_(array) {}
486 Object* operator[](int index) { return *array_[index]; }
487
488 private:
489 Handle<Object>* array_;
490};
491
492
493class ParameterArguments BASE_EMBEDDED {
494 public:
495 explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
496 Object*& operator[](int index) { return *(parameters_ - index - 1); }
497
498 private:
499 Object** parameters_;
500};
501
502} // namespace
503
504
505RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400506 HandleScope scope(isolate);
507 DCHECK(args.length() == 1);
508 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 // This generic runtime function can also be used when the caller has been
510 // inlined, we use the slow but accurate {GetCallerArguments}.
511 int argument_count = 0;
512 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100513 GetCallerArguments(isolate, &argument_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000514 HandleArguments argument_getter(arguments.get());
515 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
516}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400517
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400518
Ben Murdoch097c5b22016-05-18 11:27:45 +0100519RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100521 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000522 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
523 // This generic runtime function can also be used when the caller has been
524 // inlined, we use the slow but accurate {GetCallerArguments}.
525 int argument_count = 0;
526 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100527 GetCallerArguments(isolate, &argument_count);
528 Handle<JSObject> result =
529 isolate->factory()->NewArgumentsObject(callee, argument_count);
530 if (argument_count) {
531 Handle<FixedArray> array =
532 isolate->factory()->NewUninitializedFixedArray(argument_count);
533 DisallowHeapAllocation no_gc;
534 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
535 for (int i = 0; i < argument_count; i++) {
536 array->set(i, *arguments[i], mode);
537 }
538 result->set_elements(*array);
539 }
540 return *result;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000541}
542
543
Ben Murdoch097c5b22016-05-18 11:27:45 +0100544RUNTIME_FUNCTION(Runtime_NewRestParameter) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000545 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100546 DCHECK_EQ(1, args.length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000547 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
Ben Murdoch097c5b22016-05-18 11:27:45 +0100548 int start_index = callee->shared()->internal_formal_parameter_count();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 // This generic runtime function can also be used when the caller has been
550 // inlined, we use the slow but accurate {GetCallerArguments}.
551 int argument_count = 0;
552 base::SmartArrayPointer<Handle<Object>> arguments =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100553 GetCallerArguments(isolate, &argument_count);
554 int num_elements = std::max(0, argument_count - start_index);
Ben Murdochda12d292016-06-02 14:46:10 +0100555 Handle<JSObject> result =
556 isolate->factory()->NewJSArray(FAST_ELEMENTS, num_elements, num_elements,
557 DONT_INITIALIZE_ARRAY_ELEMENTS);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100558 {
559 DisallowHeapAllocation no_gc;
560 FixedArray* elements = FixedArray::cast(result->elements());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100561 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100562 for (int i = 0; i < num_elements; i++) {
563 elements->set(i, *arguments[i + start_index], mode);
564 }
565 }
566 return *result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400567}
568
569
570RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
571 HandleScope scope(isolate);
572 DCHECK(args.length() == 3);
573 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
574 Object** parameters = reinterpret_cast<Object**>(args[1]);
575 CONVERT_SMI_ARG_CHECKED(argument_count, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 ParameterArguments argument_getter(parameters);
577 return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400578}
579
580
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400581RUNTIME_FUNCTION(Runtime_NewClosure) {
582 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 DCHECK_EQ(1, args.length());
584 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
585 Handle<Context> context(isolate->context(), isolate);
586 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
587 NOT_TENURED);
588}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590
591RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
592 HandleScope scope(isolate);
593 DCHECK_EQ(1, args.length());
594 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
595 Handle<Context> context(isolate->context(), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400596 // The caller ensures that we pretenure closures that are assigned
597 // directly to properties.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400598 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 TENURED);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400600}
601
602static Object* FindNameClash(Handle<ScopeInfo> scope_info,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 Handle<JSGlobalObject> global_object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400604 Handle<ScriptContextTable> script_context) {
605 Isolate* isolate = scope_info->GetIsolate();
606 for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
607 Handle<String> name(scope_info->ContextLocalName(var));
608 VariableMode mode = scope_info->ContextLocalMode(var);
609 ScriptContextTable::LookupResult lookup;
610 if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
611 if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100612 // ES#sec-globaldeclarationinstantiation 5.b:
613 // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
614 // exception.
615 return ThrowRedeclarationError(isolate, name,
616 RedeclarationType::kSyntaxError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 }
618 }
619
620 if (IsLexicalVariableMode(mode)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100621 LookupIterator it(global_object, name, global_object,
Ben Murdochc5610432016-08-08 18:44:38 +0100622 LookupIterator::OWN_SKIP_INTERCEPTOR);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400623 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 if (!maybe.IsJust()) return isolate->heap()->exception();
625 if ((maybe.FromJust() & DONT_DELETE) != 0) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100626 // ES#sec-globaldeclarationinstantiation 5.a:
627 // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
628 // exception.
629 // ES#sec-globaldeclarationinstantiation 5.d:
630 // If hasRestrictedGlobal is true, throw a SyntaxError exception.
631 return ThrowRedeclarationError(isolate, name,
632 RedeclarationType::kSyntaxError);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400633 }
634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 JSGlobalObject::InvalidatePropertyCell(global_object, name);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400636 }
637 }
638 return isolate->heap()->undefined_value();
639}
640
641
642RUNTIME_FUNCTION(Runtime_NewScriptContext) {
643 HandleScope scope(isolate);
644 DCHECK(args.length() == 2);
645
646 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
647 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000648 Handle<JSGlobalObject> global_object(function->context()->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400649 Handle<Context> native_context(global_object->native_context());
650 Handle<ScriptContextTable> script_context_table(
651 native_context->script_context_table());
652
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400653 Object* name_clash_result =
654 FindNameClash(scope_info, global_object, script_context_table);
655 if (isolate->has_pending_exception()) return name_clash_result;
656
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 // Script contexts have a canonical empty function as their closure, not the
658 // anonymous closure containing the global code. See
659 // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
660 Handle<JSFunction> closure(
661 function->shared()->IsBuiltin() ? *function : native_context->closure());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400662 Handle<Context> result =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000663 isolate->factory()->NewScriptContext(closure, scope_info);
664
665 result->InitializeGlobalSlots();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400666
667 DCHECK(function->context() == isolate->context());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 DCHECK(*global_object == result->global_object());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400669
670 Handle<ScriptContextTable> new_script_context_table =
671 ScriptContextTable::Extend(script_context_table, result);
672 native_context->set_script_context_table(*new_script_context_table);
673 return *result;
674}
675
676
677RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
678 HandleScope scope(isolate);
679 DCHECK(args.length() == 1);
680
681 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
682
683 DCHECK(function->context() == isolate->context());
684 int length = function->shared()->scope_info()->ContextLength();
685 return *isolate->factory()->NewFunctionContext(length, function);
686}
687
688
689RUNTIME_FUNCTION(Runtime_PushWithContext) {
690 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 DCHECK_EQ(2, args.length());
692 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
693 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400694 Handle<Context> current(isolate->context());
695 Handle<Context> context =
696 isolate->factory()->NewWithContext(function, current, extension_object);
697 isolate->set_context(*context);
698 return *context;
699}
700
701
702RUNTIME_FUNCTION(Runtime_PushCatchContext) {
703 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000704 DCHECK_EQ(3, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400705 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
706 CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400708 Handle<Context> current(isolate->context());
709 Handle<Context> context = isolate->factory()->NewCatchContext(
710 function, current, name, thrown_object);
711 isolate->set_context(*context);
712 return *context;
713}
714
715
716RUNTIME_FUNCTION(Runtime_PushBlockContext) {
717 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 DCHECK_EQ(2, args.length());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400719 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400721 Handle<Context> current(isolate->context());
722 Handle<Context> context =
723 isolate->factory()->NewBlockContext(function, current, scope_info);
724 isolate->set_context(*context);
725 return *context;
726}
727
728
729RUNTIME_FUNCTION(Runtime_IsJSModule) {
730 SealHandleScope shs(isolate);
731 DCHECK(args.length() == 1);
732 CONVERT_ARG_CHECKED(Object, obj, 0);
733 return isolate->heap()->ToBoolean(obj->IsJSModule());
734}
735
736
737RUNTIME_FUNCTION(Runtime_PushModuleContext) {
738 SealHandleScope shs(isolate);
739 DCHECK(args.length() == 2);
740 CONVERT_SMI_ARG_CHECKED(index, 0);
741
742 if (!args[1]->IsScopeInfo()) {
743 // Module already initialized. Find hosting context and retrieve context.
744 Context* host = Context::cast(isolate->context())->script_context();
745 Context* context = Context::cast(host->get(index));
746 DCHECK(context->previous() == isolate->context());
747 isolate->set_context(context);
748 return context;
749 }
750
751 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
752
753 // Allocate module context.
754 HandleScope scope(isolate);
755 Factory* factory = isolate->factory();
756 Handle<Context> context = factory->NewModuleContext(scope_info);
757 Handle<JSModule> module = factory->NewJSModule(context, scope_info);
758 context->set_module(*module);
759 Context* previous = isolate->context();
760 context->set_previous(previous);
761 context->set_closure(previous->closure());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 context->set_native_context(previous->native_context());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400763 isolate->set_context(*context);
764
765 // Find hosting scope and initialize internal variable holding module there.
766 previous->script_context()->set(index, *context);
767
768 return *context;
769}
770
771
772RUNTIME_FUNCTION(Runtime_DeclareModules) {
773 HandleScope scope(isolate);
774 DCHECK(args.length() == 1);
775 CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
776 Context* host_context = isolate->context();
777
778 for (int i = 0; i < descriptions->length(); ++i) {
779 Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
780 int host_index = description->host_index();
781 Handle<Context> context(Context::cast(host_context->get(host_index)));
782 Handle<JSModule> module(context->module());
783
784 for (int j = 0; j < description->length(); ++j) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100785 Handle<String> name(description->name(j), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400786 VariableMode mode = description->mode(j);
787 int index = description->index(j);
788 switch (mode) {
789 case VAR:
790 case LET:
791 case CONST:
Ben Murdochc5610432016-08-08 18:44:38 +0100792 case CONST_LEGACY: {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400793 PropertyAttributes attr =
794 IsImmutableVariableMode(mode) ? FROZEN : SEALED;
795 Handle<AccessorInfo> info =
796 Accessors::MakeModuleExport(name, index, attr);
797 Handle<Object> result =
798 JSObject::SetAccessor(module, info).ToHandleChecked();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100799 DCHECK(!result->IsUndefined(isolate));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400800 USE(result);
801 break;
802 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400803 case TEMPORARY:
804 case DYNAMIC:
805 case DYNAMIC_GLOBAL:
806 case DYNAMIC_LOCAL:
807 UNREACHABLE();
808 }
809 }
810
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000811 if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR)
812 .IsNothing()) {
813 DCHECK(false);
814 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400815 }
816
817 DCHECK(!isolate->has_pending_exception());
818 return isolate->heap()->undefined_value();
819}
820
821
822RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
823 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100824 DCHECK_EQ(1, args.length());
825 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400826
827 int index;
828 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100829 BindingFlags flags;
830 Handle<Object> holder = isolate->context()->Lookup(
831 name, FOLLOW_CHAINS, &index, &attributes, &flags);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400832
833 // If the slot was not found the result is true.
834 if (holder.is_null()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 // In case of JSProxy, an exception might have been thrown.
836 if (isolate->has_pending_exception()) return isolate->heap()->exception();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400837 return isolate->heap()->true_value();
838 }
839
840 // If the slot was found in a context, it should be DONT_DELETE.
841 if (holder->IsContext()) {
842 return isolate->heap()->false_value();
843 }
844
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 // The slot was found in a JSReceiver, either a context extension object,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400846 // the global object, or the subject of a with. Try to delete it
847 // (respecting DONT_DELETE).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
849 Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
850 MAYBE_RETURN(result, isolate->heap()->exception());
851 return isolate->heap()->ToBoolean(result.FromJust());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400852}
853
854
Ben Murdoch097c5b22016-05-18 11:27:45 +0100855namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856
Ben Murdoch097c5b22016-05-18 11:27:45 +0100857MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
858 Object::ShouldThrow should_throw,
859 Handle<Object>* receiver_return = nullptr) {
860 Isolate* const isolate = name->GetIsolate();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400861
862 int index;
863 PropertyAttributes attributes;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100864 BindingFlags flags;
865 Handle<Object> holder = isolate->context()->Lookup(
866 name, FOLLOW_CHAINS, &index, &attributes, &flags);
867 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 if (index != Context::kNotFound) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400870 DCHECK(holder->IsContext());
871 // If the "property" we were looking for is a local variable, the
872 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
873 Handle<Object> receiver = isolate->factory()->undefined_value();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100874 Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875 // Check for uninitialized bindings.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100876 switch (flags) {
Ben Murdochc5610432016-08-08 18:44:38 +0100877 case BINDING_CHECK_INITIALIZED:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100878 if (value->IsTheHole(isolate)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100879 THROW_NEW_ERROR(isolate,
880 NewReferenceError(MessageTemplate::kNotDefined, name),
881 Object);
882 }
883 // FALLTHROUGH
Ben Murdochc5610432016-08-08 18:44:38 +0100884 case BINDING_IS_INITIALIZED:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100885 DCHECK(!value->IsTheHole(isolate));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100886 if (receiver_return) *receiver_return = receiver;
887 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400888 case MISSING_BINDING:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100889 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400890 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100891 UNREACHABLE();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400892 }
893
894 // Otherwise, if the slot was found the holder is a context extension
895 // object, subject of a with, or a global object. We read the named
896 // property from it.
897 if (!holder.is_null()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400898 // No need to unhole the value here. This is taken care of by the
899 // GetProperty function.
900 Handle<Object> value;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100901 ASSIGN_RETURN_ON_EXCEPTION(
902 isolate, value, Object::GetProperty(holder, name),
903 Object);
904 if (receiver_return) {
905 *receiver_return =
906 (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
907 ? Handle<Object>::cast(isolate->factory()->undefined_value())
908 : holder;
909 }
910 return value;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400911 }
912
Ben Murdoch097c5b22016-05-18 11:27:45 +0100913 if (should_throw == Object::THROW_ON_ERROR) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400914 // The property doesn't exist - throw exception.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100915 THROW_NEW_ERROR(
916 isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400917 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100918
919 // The property doesn't exist - return undefined.
920 if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
921 return isolate->factory()->undefined_value();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400922}
923
Ben Murdoch097c5b22016-05-18 11:27:45 +0100924} // namespace
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400925
926
Ben Murdoch097c5b22016-05-18 11:27:45 +0100927RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400928 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100929 DCHECK_EQ(1, args.length());
930 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100931 RETURN_RESULT_OR_FAILURE(isolate,
932 LoadLookupSlot(name, Object::THROW_ON_ERROR));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100933}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400934
Ben Murdoch097c5b22016-05-18 11:27:45 +0100935
936RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
937 HandleScope scope(isolate);
938 DCHECK_EQ(1, args.length());
939 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100940 RETURN_RESULT_OR_FAILURE(isolate, LoadLookupSlot(name, Object::DONT_THROW));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100941}
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);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001024 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, SLOPPY));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001025}
1026
1027
Ben Murdoch097c5b22016-05-18 11:27:45 +01001028RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029 HandleScope scope(isolate);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001030 DCHECK_EQ(2, args.length());
1031 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1032 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001033 RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034}
1035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001036} // namespace internal
1037} // namespace v8