1 // 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 
5 #include "src/runtime/runtime-utils.h"
6 
7 #include <memory>
8 
9 #include "src/accessors.h"
10 #include "src/arguments.h"
11 #include "src/ast/scopes.h"
12 #include "src/deoptimizer.h"
13 #include "src/frames-inl.h"
14 #include "src/isolate-inl.h"
15 #include "src/messages.h"
16 
17 namespace v8 {
18 namespace internal {
19 
RUNTIME_FUNCTION(Runtime_ThrowConstAssignError)20 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
21   HandleScope scope(isolate);
22   THROW_NEW_ERROR_RETURN_FAILURE(isolate,
23                                  NewTypeError(MessageTemplate::kConstAssign));
24 }
25 
26 namespace {
27 
28 enum class RedeclarationType { kSyntaxError = 0, kTypeError = 1 };
29 
ThrowRedeclarationError(Isolate * isolate,Handle<String> name,RedeclarationType redeclaration_type)30 Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name,
31                                 RedeclarationType redeclaration_type) {
32   HandleScope scope(isolate);
33   if (redeclaration_type == RedeclarationType::kSyntaxError) {
34     THROW_NEW_ERROR_RETURN_FAILURE(
35         isolate, NewSyntaxError(MessageTemplate::kVarRedeclaration, name));
36   } else {
37     THROW_NEW_ERROR_RETURN_FAILURE(
38         isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
39   }
40 }
41 
42 
43 // May throw a RedeclarationError.
DeclareGlobal(Isolate * isolate,Handle<JSGlobalObject> global,Handle<String> name,Handle<Object> value,PropertyAttributes attr,bool is_var,bool is_function_declaration,RedeclarationType redeclaration_type,Handle<TypeFeedbackVector> feedback_vector=Handle<TypeFeedbackVector> (),FeedbackVectorSlot slot=FeedbackVectorSlot::Invalid ())44 Object* DeclareGlobal(
45     Isolate* isolate, Handle<JSGlobalObject> global, Handle<String> name,
46     Handle<Object> value, PropertyAttributes attr, bool is_var,
47     bool is_function_declaration, RedeclarationType redeclaration_type,
48     Handle<TypeFeedbackVector> feedback_vector = Handle<TypeFeedbackVector>(),
49     FeedbackVectorSlot slot = FeedbackVectorSlot::Invalid()) {
50   Handle<ScriptContextTable> script_contexts(
51       global->native_context()->script_context_table());
52   ScriptContextTable::LookupResult lookup;
53   if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
54       IsLexicalVariableMode(lookup.mode)) {
55     // ES#sec-globaldeclarationinstantiation 6.a:
56     // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
57     // exception.
58     return ThrowRedeclarationError(isolate, name,
59                                    RedeclarationType::kSyntaxError);
60   }
61 
62   // Do the lookup own properties only, see ES5 erratum.
63   LookupIterator::Configuration lookup_config(
64       LookupIterator::Configuration::OWN_SKIP_INTERCEPTOR);
65   if (is_function_declaration) {
66     // For function declarations, use the interceptor on the declaration. For
67     // non-functions, use it only on initialization.
68     lookup_config = LookupIterator::Configuration::OWN;
69   }
70   LookupIterator it(global, name, global, lookup_config);
71   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
72   if (!maybe.IsJust()) return isolate->heap()->exception();
73 
74   if (it.IsFound()) {
75     PropertyAttributes old_attributes = maybe.FromJust();
76     // The name was declared before; check for conflicting re-declarations.
77 
78     // Skip var re-declarations.
79     if (is_var) return isolate->heap()->undefined_value();
80 
81     DCHECK(is_function_declaration);
82     if ((old_attributes & DONT_DELETE) != 0) {
83       // Only allow reconfiguring globals to functions in user code (no
84       // natives, which are marked as read-only).
85       DCHECK((attr & READ_ONLY) == 0);
86 
87       // Check whether we can reconfigure the existing property into a
88       // function.
89       PropertyDetails old_details = it.property_details();
90       if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
91           (it.state() == LookupIterator::ACCESSOR &&
92            it.GetAccessors()->IsAccessorPair())) {
93         // ECMA-262 section 15.1.11 GlobalDeclarationInstantiation 5.d:
94         // If hasRestrictedGlobal is true, throw a SyntaxError exception.
95         // ECMA-262 section 18.2.1.3 EvalDeclarationInstantiation 8.a.iv.1.b:
96         // If fnDefinable is false, throw a TypeError exception.
97         return ThrowRedeclarationError(isolate, name, redeclaration_type);
98       }
99       // If the existing property is not configurable, keep its attributes. Do
100       attr = old_attributes;
101     }
102 
103     // If the current state is ACCESSOR, this could mean it's an AccessorInfo
104     // type property. We are not allowed to call into such setters during global
105     // function declaration since this would break e.g., onload. Meaning
106     // 'function onload() {}' would invalidly register that function as the
107     // onload callback. To avoid this situation, we first delete the property
108     // before readding it as a regular data property below.
109     if (it.state() == LookupIterator::ACCESSOR) it.Delete();
110   }
111 
112   if (is_function_declaration) {
113     it.Restart();
114   }
115 
116   // Define or redefine own property.
117   RETURN_FAILURE_ON_EXCEPTION(
118       isolate, JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, attr));
119 
120   if (!feedback_vector.is_null()) {
121     DCHECK_EQ(*global, *it.GetHolder<Object>());
122     // Preinitialize the feedback slot if the global object does not have
123     // named interceptor or the interceptor is not masking.
124     if (!global->HasNamedInterceptor() ||
125         global->GetNamedInterceptor()->non_masking()) {
126       LoadGlobalICNexus nexus(feedback_vector, slot);
127       nexus.ConfigurePropertyCellMode(it.GetPropertyCell());
128     }
129   }
130   return isolate->heap()->undefined_value();
131 }
132 
DeclareGlobals(Isolate * isolate,Handle<FixedArray> pairs,int flags,Handle<TypeFeedbackVector> feedback_vector)133 Object* DeclareGlobals(Isolate* isolate, Handle<FixedArray> pairs, int flags,
134                        Handle<TypeFeedbackVector> feedback_vector) {
135   HandleScope scope(isolate);
136   Handle<JSGlobalObject> global(isolate->global_object());
137   Handle<Context> context(isolate->context());
138 
139   // Traverse the name/value pairs and set the properties.
140   int length = pairs->length();
141   FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < length, i += 2, {
142     FeedbackVectorSlot slot(Smi::cast(pairs->get(i))->value());
143     Handle<String> name(feedback_vector->GetName(slot), isolate);
144     Handle<Object> initial_value(pairs->get(i + 1), isolate);
145 
146     bool is_var = initial_value->IsUndefined(isolate);
147     bool is_function = initial_value->IsSharedFunctionInfo();
148     DCHECK_EQ(1, BoolToInt(is_var) + BoolToInt(is_function));
149 
150     Handle<Object> value;
151     if (is_function) {
152       // Copy the function and update its context. Use it as value.
153       Handle<SharedFunctionInfo> shared =
154           Handle<SharedFunctionInfo>::cast(initial_value);
155       Handle<JSFunction> function =
156           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
157                                                                 TENURED);
158       value = function;
159     } else {
160       value = isolate->factory()->undefined_value();
161     }
162 
163     // Compute the property attributes. According to ECMA-262,
164     // the property must be non-configurable except in eval.
165     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
166     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
167     int attr = NONE;
168     if (is_function && is_native) attr |= READ_ONLY;
169     if (!is_eval) attr |= DONT_DELETE;
170 
171     // ES#sec-globaldeclarationinstantiation 5.d:
172     // If hasRestrictedGlobal is true, throw a SyntaxError exception.
173     Object* result = DeclareGlobal(
174         isolate, global, name, value, static_cast<PropertyAttributes>(attr),
175         is_var, is_function, RedeclarationType::kSyntaxError, feedback_vector,
176         slot);
177     if (isolate->has_pending_exception()) return result;
178   });
179 
180   return isolate->heap()->undefined_value();
181 }
182 
183 }  // namespace
184 
RUNTIME_FUNCTION(Runtime_DeclareGlobals)185 RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
186   HandleScope scope(isolate);
187   DCHECK_EQ(3, args.length());
188 
189   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
190   CONVERT_SMI_ARG_CHECKED(flags, 1);
191   CONVERT_ARG_HANDLE_CHECKED(TypeFeedbackVector, feedback_vector, 2);
192 
193   return DeclareGlobals(isolate, pairs, flags, feedback_vector);
194 }
195 
196 // TODO(ishell): merge this with Runtime::kDeclareGlobals once interpreter
197 // is able to pass feedback vector.
RUNTIME_FUNCTION(Runtime_DeclareGlobalsForInterpreter)198 RUNTIME_FUNCTION(Runtime_DeclareGlobalsForInterpreter) {
199   HandleScope scope(isolate);
200   DCHECK_EQ(3, args.length());
201 
202   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
203   CONVERT_SMI_ARG_CHECKED(flags, 1);
204   CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 2);
205 
206   Handle<TypeFeedbackVector> feedback_vector(closure->feedback_vector(),
207                                              isolate);
208   return DeclareGlobals(isolate, pairs, flags, feedback_vector);
209 }
210 
RUNTIME_FUNCTION(Runtime_InitializeVarGlobal)211 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
212   HandleScope scope(isolate);
213   DCHECK_EQ(3, args.length());
214   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
215   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
216   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
217 
218   Handle<JSGlobalObject> global(isolate->global_object());
219   RETURN_RESULT_OR_FAILURE(
220       isolate, Object::SetProperty(global, name, value, language_mode));
221 }
222 
223 namespace {
224 
DeclareEvalHelper(Isolate * isolate,Handle<String> name,Handle<Object> value)225 Object* DeclareEvalHelper(Isolate* isolate, Handle<String> name,
226                           Handle<Object> value) {
227   // Declarations are always made in a function, native, or script context, or
228   // a declaration block scope. Since this is called from eval, the context
229   // passed is the context of the caller, which may be some nested context and
230   // not the declaration context.
231   Handle<Context> context_arg(isolate->context(), isolate);
232   Handle<Context> context(context_arg->declaration_context(), isolate);
233 
234   DCHECK(context->IsFunctionContext() || context->IsNativeContext() ||
235          context->IsScriptContext() ||
236          (context->IsBlockContext() && context->has_extension()));
237 
238   bool is_function = value->IsJSFunction();
239   bool is_var = !is_function;
240   DCHECK(!is_var || value->IsUndefined(isolate));
241 
242   int index;
243   PropertyAttributes attributes;
244   InitializationFlag init_flag;
245   VariableMode mode;
246 
247   // Check for a conflict with a lexically scoped variable
248   context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes, &init_flag,
249                       &mode);
250   if (attributes != ABSENT && IsLexicalVariableMode(mode)) {
251     // ES#sec-evaldeclarationinstantiation 5.a.i.1:
252     // If varEnvRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
253     // exception.
254     // ES#sec-evaldeclarationinstantiation 5.d.ii.2.a.i:
255     // Throw a SyntaxError exception.
256     return ThrowRedeclarationError(isolate, name,
257                                    RedeclarationType::kSyntaxError);
258   }
259 
260   Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
261                                           &attributes, &init_flag, &mode);
262   DCHECK(!isolate->has_pending_exception());
263 
264   Handle<JSObject> object;
265 
266   if (attributes != ABSENT && holder->IsJSGlobalObject()) {
267     // ES#sec-evaldeclarationinstantiation 8.a.iv.1.b:
268     // If fnDefinable is false, throw a TypeError exception.
269     return DeclareGlobal(isolate, Handle<JSGlobalObject>::cast(holder), name,
270                          value, NONE, is_var, is_function,
271                          RedeclarationType::kTypeError);
272   }
273   if (context_arg->extension()->IsJSGlobalObject()) {
274     Handle<JSGlobalObject> global(
275         JSGlobalObject::cast(context_arg->extension()), isolate);
276     return DeclareGlobal(isolate, global, name, value, NONE, is_var,
277                          is_function, RedeclarationType::kTypeError);
278   } else if (context->IsScriptContext()) {
279     DCHECK(context->global_object()->IsJSGlobalObject());
280     Handle<JSGlobalObject> global(
281         JSGlobalObject::cast(context->global_object()), isolate);
282     return DeclareGlobal(isolate, global, name, value, NONE, is_var,
283                          is_function, RedeclarationType::kTypeError);
284   }
285 
286   if (attributes != ABSENT) {
287     DCHECK_EQ(NONE, attributes);
288 
289     // Skip var re-declarations.
290     if (is_var) return isolate->heap()->undefined_value();
291 
292     DCHECK(is_function);
293     if (index != Context::kNotFound) {
294       DCHECK(holder.is_identical_to(context));
295       context->set(index, *value);
296       return isolate->heap()->undefined_value();
297     }
298 
299     object = Handle<JSObject>::cast(holder);
300 
301   } else if (context->has_extension()) {
302     // Sloppy varblock contexts might not have an extension object yet,
303     // in which case their extension is a ScopeInfo.
304     if (context->extension()->IsScopeInfo()) {
305       DCHECK(context->IsBlockContext());
306       object = isolate->factory()->NewJSObject(
307           isolate->context_extension_function());
308       Handle<HeapObject> extension = isolate->factory()->NewContextExtension(
309           handle(context->scope_info()), object);
310       context->set_extension(*extension);
311     } else {
312       object = handle(context->extension_object(), isolate);
313     }
314     DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
315   } else {
316     DCHECK(context->IsFunctionContext());
317     object =
318         isolate->factory()->NewJSObject(isolate->context_extension_function());
319     context->set_extension(*object);
320   }
321 
322   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
323                                            object, name, value, NONE));
324 
325   return isolate->heap()->undefined_value();
326 }
327 
328 }  // namespace
329 
RUNTIME_FUNCTION(Runtime_DeclareEvalFunction)330 RUNTIME_FUNCTION(Runtime_DeclareEvalFunction) {
331   HandleScope scope(isolate);
332   DCHECK_EQ(2, args.length());
333   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
334   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
335   return DeclareEvalHelper(isolate, name, value);
336 }
337 
RUNTIME_FUNCTION(Runtime_DeclareEvalVar)338 RUNTIME_FUNCTION(Runtime_DeclareEvalVar) {
339   HandleScope scope(isolate);
340   DCHECK_EQ(1, args.length());
341   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
342   return DeclareEvalHelper(isolate, name,
343                            isolate->factory()->undefined_value());
344 }
345 
346 namespace {
347 
348 // Find the arguments of the JavaScript function invocation that called
349 // into C++ code. Collect these in a newly allocated array of handles.
GetCallerArguments(Isolate * isolate,int * total_argc)350 std::unique_ptr<Handle<Object>[]> GetCallerArguments(Isolate* isolate,
351                                                      int* total_argc) {
352   // Find frame containing arguments passed to the caller.
353   JavaScriptFrameIterator it(isolate);
354   JavaScriptFrame* frame = it.frame();
355   List<JSFunction*> functions(2);
356   frame->GetFunctions(&functions);
357   if (functions.length() > 1) {
358     int inlined_jsframe_index = functions.length() - 1;
359     TranslatedState translated_values(frame);
360     translated_values.Prepare(false, frame->fp());
361 
362     int argument_count = 0;
363     TranslatedFrame* translated_frame =
364         translated_values.GetArgumentsInfoFromJSFrameIndex(
365             inlined_jsframe_index, &argument_count);
366     TranslatedFrame::iterator iter = translated_frame->begin();
367 
368     // Skip the function.
369     iter++;
370 
371     // Skip the receiver.
372     iter++;
373     argument_count--;
374 
375     *total_argc = argument_count;
376     std::unique_ptr<Handle<Object>[]> param_data(
377         NewArray<Handle<Object>>(*total_argc));
378     bool should_deoptimize = false;
379     for (int i = 0; i < argument_count; i++) {
380       should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
381       Handle<Object> value = iter->GetValue();
382       param_data[i] = value;
383       iter++;
384     }
385 
386     if (should_deoptimize) {
387       translated_values.StoreMaterializedValuesAndDeopt();
388     }
389 
390     return param_data;
391   } else {
392     it.AdvanceToArgumentsFrame();
393     frame = it.frame();
394     int args_count = frame->ComputeParametersCount();
395 
396     *total_argc = args_count;
397     std::unique_ptr<Handle<Object>[]> param_data(
398         NewArray<Handle<Object>>(*total_argc));
399     for (int i = 0; i < args_count; i++) {
400       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
401       param_data[i] = val;
402     }
403     return param_data;
404   }
405 }
406 
407 template <typename T>
NewSloppyArguments(Isolate * isolate,Handle<JSFunction> callee,T parameters,int argument_count)408 Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
409                                     T parameters, int argument_count) {
410   CHECK(!IsSubclassConstructor(callee->shared()->kind()));
411   DCHECK(callee->shared()->has_simple_parameters());
412   Handle<JSObject> result =
413       isolate->factory()->NewArgumentsObject(callee, argument_count);
414 
415   // Allocate the elements if needed.
416   int parameter_count = callee->shared()->internal_formal_parameter_count();
417   if (argument_count > 0) {
418     if (parameter_count > 0) {
419       int mapped_count = Min(argument_count, parameter_count);
420       Handle<FixedArray> parameter_map =
421           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
422       parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
423       result->set_map(isolate->native_context()->fast_aliased_arguments_map());
424       result->set_elements(*parameter_map);
425 
426       // Store the context and the arguments array at the beginning of the
427       // parameter map.
428       Handle<Context> context(isolate->context());
429       Handle<FixedArray> arguments =
430           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
431       parameter_map->set(0, *context);
432       parameter_map->set(1, *arguments);
433 
434       // Loop over the actual parameters backwards.
435       int index = argument_count - 1;
436       while (index >= mapped_count) {
437         // These go directly in the arguments array and have no
438         // corresponding slot in the parameter map.
439         arguments->set(index, parameters[index]);
440         --index;
441       }
442 
443       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
444       while (index >= 0) {
445         // Detect duplicate names to the right in the parameter list.
446         Handle<String> name(scope_info->ParameterName(index));
447         int context_local_count = scope_info->ContextLocalCount();
448         bool duplicate = false;
449         for (int j = index + 1; j < parameter_count; ++j) {
450           if (scope_info->ParameterName(j) == *name) {
451             duplicate = true;
452             break;
453           }
454         }
455 
456         if (duplicate) {
457           // This goes directly in the arguments array with a hole in the
458           // parameter map.
459           arguments->set(index, parameters[index]);
460           parameter_map->set_the_hole(index + 2);
461         } else {
462           // The context index goes in the parameter map with a hole in the
463           // arguments array.
464           int context_index = -1;
465           for (int j = 0; j < context_local_count; ++j) {
466             if (scope_info->ContextLocalName(j) == *name) {
467               context_index = j;
468               break;
469             }
470           }
471 
472           DCHECK(context_index >= 0);
473           arguments->set_the_hole(index);
474           parameter_map->set(
475               index + 2,
476               Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
477         }
478 
479         --index;
480       }
481     } else {
482       // If there is no aliasing, the arguments object elements are not
483       // special in any way.
484       Handle<FixedArray> elements =
485           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
486       result->set_elements(*elements);
487       for (int i = 0; i < argument_count; ++i) {
488         elements->set(i, parameters[i]);
489       }
490     }
491   }
492   return result;
493 }
494 
495 
496 class HandleArguments BASE_EMBEDDED {
497  public:
HandleArguments(Handle<Object> * array)498   explicit HandleArguments(Handle<Object>* array) : array_(array) {}
operator [](int index)499   Object* operator[](int index) { return *array_[index]; }
500 
501  private:
502   Handle<Object>* array_;
503 };
504 
505 
506 class ParameterArguments BASE_EMBEDDED {
507  public:
ParameterArguments(Object ** parameters)508   explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
operator [](int index)509   Object*& operator[](int index) { return *(parameters_ - index - 1); }
510 
511  private:
512   Object** parameters_;
513 };
514 
515 }  // namespace
516 
517 
RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic)518 RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
519   HandleScope scope(isolate);
520   DCHECK(args.length() == 1);
521   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
522   // This generic runtime function can also be used when the caller has been
523   // inlined, we use the slow but accurate {GetCallerArguments}.
524   int argument_count = 0;
525   std::unique_ptr<Handle<Object>[]> arguments =
526       GetCallerArguments(isolate, &argument_count);
527   HandleArguments argument_getter(arguments.get());
528   return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
529 }
530 
531 
RUNTIME_FUNCTION(Runtime_NewStrictArguments)532 RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
533   HandleScope scope(isolate);
534   DCHECK_EQ(1, args.length());
535   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
536   // This generic runtime function can also be used when the caller has been
537   // inlined, we use the slow but accurate {GetCallerArguments}.
538   int argument_count = 0;
539   std::unique_ptr<Handle<Object>[]> arguments =
540       GetCallerArguments(isolate, &argument_count);
541   Handle<JSObject> result =
542       isolate->factory()->NewArgumentsObject(callee, argument_count);
543   if (argument_count) {
544     Handle<FixedArray> array =
545         isolate->factory()->NewUninitializedFixedArray(argument_count);
546     DisallowHeapAllocation no_gc;
547     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
548     for (int i = 0; i < argument_count; i++) {
549       array->set(i, *arguments[i], mode);
550     }
551     result->set_elements(*array);
552   }
553   return *result;
554 }
555 
556 
RUNTIME_FUNCTION(Runtime_NewRestParameter)557 RUNTIME_FUNCTION(Runtime_NewRestParameter) {
558   HandleScope scope(isolate);
559   DCHECK_EQ(1, args.length());
560   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
561   int start_index = callee->shared()->internal_formal_parameter_count();
562   // This generic runtime function can also be used when the caller has been
563   // inlined, we use the slow but accurate {GetCallerArguments}.
564   int argument_count = 0;
565   std::unique_ptr<Handle<Object>[]> arguments =
566       GetCallerArguments(isolate, &argument_count);
567   int num_elements = std::max(0, argument_count - start_index);
568   Handle<JSObject> result =
569       isolate->factory()->NewJSArray(FAST_ELEMENTS, num_elements, num_elements,
570                                      DONT_INITIALIZE_ARRAY_ELEMENTS);
571   {
572     DisallowHeapAllocation no_gc;
573     FixedArray* elements = FixedArray::cast(result->elements());
574     WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
575     for (int i = 0; i < num_elements; i++) {
576       elements->set(i, *arguments[i + start_index], mode);
577     }
578   }
579   return *result;
580 }
581 
582 
RUNTIME_FUNCTION(Runtime_NewSloppyArguments)583 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
584   HandleScope scope(isolate);
585   DCHECK(args.length() == 3);
586   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
587   Object** parameters = reinterpret_cast<Object**>(args[1]);
588   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
589   ParameterArguments argument_getter(parameters);
590   return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
591 }
592 
593 
RUNTIME_FUNCTION(Runtime_NewClosure)594 RUNTIME_FUNCTION(Runtime_NewClosure) {
595   HandleScope scope(isolate);
596   DCHECK_EQ(1, args.length());
597   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
598   Handle<Context> context(isolate->context(), isolate);
599   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
600                                                                 NOT_TENURED);
601 }
602 
603 
RUNTIME_FUNCTION(Runtime_NewClosure_Tenured)604 RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
605   HandleScope scope(isolate);
606   DCHECK_EQ(1, args.length());
607   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
608   Handle<Context> context(isolate->context(), isolate);
609   // The caller ensures that we pretenure closures that are assigned
610   // directly to properties.
611   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
612                                                                 TENURED);
613 }
614 
FindNameClash(Handle<ScopeInfo> scope_info,Handle<JSGlobalObject> global_object,Handle<ScriptContextTable> script_context)615 static Object* FindNameClash(Handle<ScopeInfo> scope_info,
616                              Handle<JSGlobalObject> global_object,
617                              Handle<ScriptContextTable> script_context) {
618   Isolate* isolate = scope_info->GetIsolate();
619   for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
620     Handle<String> name(scope_info->ContextLocalName(var));
621     VariableMode mode = scope_info->ContextLocalMode(var);
622     ScriptContextTable::LookupResult lookup;
623     if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
624       if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
625         // ES#sec-globaldeclarationinstantiation 5.b:
626         // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError
627         // exception.
628         return ThrowRedeclarationError(isolate, name,
629                                        RedeclarationType::kSyntaxError);
630       }
631     }
632 
633     if (IsLexicalVariableMode(mode)) {
634       LookupIterator it(global_object, name, global_object,
635                         LookupIterator::OWN_SKIP_INTERCEPTOR);
636       Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
637       if (!maybe.IsJust()) return isolate->heap()->exception();
638       if ((maybe.FromJust() & DONT_DELETE) != 0) {
639         // ES#sec-globaldeclarationinstantiation 5.a:
640         // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError
641         // exception.
642         // ES#sec-globaldeclarationinstantiation 5.d:
643         // If hasRestrictedGlobal is true, throw a SyntaxError exception.
644         return ThrowRedeclarationError(isolate, name,
645                                        RedeclarationType::kSyntaxError);
646       }
647 
648       JSGlobalObject::InvalidatePropertyCell(global_object, name);
649     }
650   }
651   return isolate->heap()->undefined_value();
652 }
653 
654 
RUNTIME_FUNCTION(Runtime_NewScriptContext)655 RUNTIME_FUNCTION(Runtime_NewScriptContext) {
656   HandleScope scope(isolate);
657   DCHECK(args.length() == 2);
658 
659   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
660   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
661   Handle<JSGlobalObject> global_object(function->context()->global_object());
662   Handle<Context> native_context(global_object->native_context());
663   Handle<ScriptContextTable> script_context_table(
664       native_context->script_context_table());
665 
666   Object* name_clash_result =
667       FindNameClash(scope_info, global_object, script_context_table);
668   if (isolate->has_pending_exception()) return name_clash_result;
669 
670   // Script contexts have a canonical empty function as their closure, not the
671   // anonymous closure containing the global code.  See
672   // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
673   Handle<JSFunction> closure(
674       function->shared()->IsBuiltin() ? *function : native_context->closure());
675   Handle<Context> result =
676       isolate->factory()->NewScriptContext(closure, scope_info);
677 
678   DCHECK(function->context() == isolate->context());
679   DCHECK(*global_object == result->global_object());
680 
681   Handle<ScriptContextTable> new_script_context_table =
682       ScriptContextTable::Extend(script_context_table, result);
683   native_context->set_script_context_table(*new_script_context_table);
684   return *result;
685 }
686 
687 
RUNTIME_FUNCTION(Runtime_NewFunctionContext)688 RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
689   HandleScope scope(isolate);
690   DCHECK(args.length() == 1);
691 
692   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
693 
694   DCHECK(function->context() == isolate->context());
695   int length = function->shared()->scope_info()->ContextLength();
696   return *isolate->factory()->NewFunctionContext(length, function);
697 }
698 
699 
RUNTIME_FUNCTION(Runtime_PushWithContext)700 RUNTIME_FUNCTION(Runtime_PushWithContext) {
701   HandleScope scope(isolate);
702   DCHECK_EQ(3, args.length());
703   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
704   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
705   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
706   Handle<Context> current(isolate->context());
707   Handle<Context> context = isolate->factory()->NewWithContext(
708       function, current, scope_info, extension_object);
709   isolate->set_context(*context);
710   return *context;
711 }
712 
RUNTIME_FUNCTION(Runtime_PushModuleContext)713 RUNTIME_FUNCTION(Runtime_PushModuleContext) {
714   HandleScope scope(isolate);
715   DCHECK_EQ(3, args.length());
716   CONVERT_ARG_HANDLE_CHECKED(Module, module, 0);
717   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
718   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 2);
719   DCHECK(function->context() == isolate->context());
720 
721   Handle<Context> context =
722       isolate->factory()->NewModuleContext(module, function, scope_info);
723   isolate->set_context(*context);
724   return *context;
725 }
726 
RUNTIME_FUNCTION(Runtime_PushCatchContext)727 RUNTIME_FUNCTION(Runtime_PushCatchContext) {
728   HandleScope scope(isolate);
729   DCHECK_EQ(4, args.length());
730   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
731   CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
732   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 2);
733   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 3);
734   Handle<Context> current(isolate->context());
735   Handle<Context> context = isolate->factory()->NewCatchContext(
736       function, current, scope_info, name, thrown_object);
737   isolate->set_context(*context);
738   return *context;
739 }
740 
741 
RUNTIME_FUNCTION(Runtime_PushBlockContext)742 RUNTIME_FUNCTION(Runtime_PushBlockContext) {
743   HandleScope scope(isolate);
744   DCHECK_EQ(2, args.length());
745   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
746   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
747   Handle<Context> current(isolate->context());
748   Handle<Context> context =
749       isolate->factory()->NewBlockContext(function, current, scope_info);
750   isolate->set_context(*context);
751   return *context;
752 }
753 
754 
RUNTIME_FUNCTION(Runtime_DeleteLookupSlot)755 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
756   HandleScope scope(isolate);
757   DCHECK_EQ(1, args.length());
758   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
759 
760   int index;
761   PropertyAttributes attributes;
762   InitializationFlag flag;
763   VariableMode mode;
764   Handle<Object> holder = isolate->context()->Lookup(
765       name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
766 
767   // If the slot was not found the result is true.
768   if (holder.is_null()) {
769     // In case of JSProxy, an exception might have been thrown.
770     if (isolate->has_pending_exception()) return isolate->heap()->exception();
771     return isolate->heap()->true_value();
772   }
773 
774   // If the slot was found in a context, it should be DONT_DELETE.
775   if (holder->IsContext()) {
776     return isolate->heap()->false_value();
777   }
778 
779   // The slot was found in a JSReceiver, either a context extension object,
780   // the global object, or the subject of a with.  Try to delete it
781   // (respecting DONT_DELETE).
782   Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
783   Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
784   MAYBE_RETURN(result, isolate->heap()->exception());
785   return isolate->heap()->ToBoolean(result.FromJust());
786 }
787 
788 
789 namespace {
790 
LoadLookupSlot(Handle<String> name,Object::ShouldThrow should_throw,Handle<Object> * receiver_return=nullptr)791 MaybeHandle<Object> LoadLookupSlot(Handle<String> name,
792                                    Object::ShouldThrow should_throw,
793                                    Handle<Object>* receiver_return = nullptr) {
794   Isolate* const isolate = name->GetIsolate();
795 
796   int index;
797   PropertyAttributes attributes;
798   InitializationFlag flag;
799   VariableMode mode;
800   Handle<Object> holder = isolate->context()->Lookup(
801       name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
802   if (isolate->has_pending_exception()) return MaybeHandle<Object>();
803 
804   if (index != Context::kNotFound) {
805     DCHECK(holder->IsContext());
806     // If the "property" we were looking for is a local variable, the
807     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
808     Handle<Object> receiver = isolate->factory()->undefined_value();
809     Handle<Object> value = handle(Context::cast(*holder)->get(index), isolate);
810     // Check for uninitialized bindings.
811     if (flag == kNeedsInitialization && value->IsTheHole(isolate)) {
812       THROW_NEW_ERROR(isolate,
813                       NewReferenceError(MessageTemplate::kNotDefined, name),
814                       Object);
815     }
816     DCHECK(!value->IsTheHole(isolate));
817     if (receiver_return) *receiver_return = receiver;
818     return value;
819   }
820 
821   // Otherwise, if the slot was found the holder is a context extension
822   // object, subject of a with, or a global object.  We read the named
823   // property from it.
824   if (!holder.is_null()) {
825     // No need to unhole the value here.  This is taken care of by the
826     // GetProperty function.
827     Handle<Object> value;
828     ASSIGN_RETURN_ON_EXCEPTION(
829         isolate, value, Object::GetProperty(holder, name),
830         Object);
831     if (receiver_return) {
832       *receiver_return =
833           (holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject())
834               ? Handle<Object>::cast(isolate->factory()->undefined_value())
835               : holder;
836     }
837     return value;
838   }
839 
840   if (should_throw == Object::THROW_ON_ERROR) {
841     // The property doesn't exist - throw exception.
842     THROW_NEW_ERROR(
843         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
844   }
845 
846   // The property doesn't exist - return undefined.
847   if (receiver_return) *receiver_return = isolate->factory()->undefined_value();
848   return isolate->factory()->undefined_value();
849 }
850 
851 }  // namespace
852 
853 
RUNTIME_FUNCTION(Runtime_LoadLookupSlot)854 RUNTIME_FUNCTION(Runtime_LoadLookupSlot) {
855   HandleScope scope(isolate);
856   DCHECK_EQ(1, args.length());
857   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
858   RETURN_RESULT_OR_FAILURE(isolate,
859                            LoadLookupSlot(name, Object::THROW_ON_ERROR));
860 }
861 
862 
RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof)863 RUNTIME_FUNCTION(Runtime_LoadLookupSlotInsideTypeof) {
864   HandleScope scope(isolate);
865   DCHECK_EQ(1, args.length());
866   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
867   RETURN_RESULT_OR_FAILURE(isolate, LoadLookupSlot(name, Object::DONT_THROW));
868 }
869 
870 
RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall)871 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotForCall) {
872   HandleScope scope(isolate);
873   DCHECK_EQ(1, args.length());
874   DCHECK(args[0]->IsString());
875   Handle<String> name = args.at<String>(0);
876   Handle<Object> value;
877   Handle<Object> receiver;
878   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
879       isolate, value, LoadLookupSlot(name, Object::THROW_ON_ERROR, &receiver),
880       MakePair(isolate->heap()->exception(), nullptr));
881   return MakePair(*value, *receiver);
882 }
883 
884 
885 namespace {
886 
StoreLookupSlot(Handle<String> name,Handle<Object> value,LanguageMode language_mode)887 MaybeHandle<Object> StoreLookupSlot(Handle<String> name, Handle<Object> value,
888                                     LanguageMode language_mode) {
889   Isolate* const isolate = name->GetIsolate();
890   Handle<Context> context(isolate->context(), isolate);
891 
892   int index;
893   PropertyAttributes attributes;
894   InitializationFlag flag;
895   VariableMode mode;
896   Handle<Object> holder =
897       context->Lookup(name, FOLLOW_CHAINS, &index, &attributes, &flag, &mode);
898   if (holder.is_null()) {
899     // In case of JSProxy, an exception might have been thrown.
900     if (isolate->has_pending_exception()) return MaybeHandle<Object>();
901   }
902 
903   // The property was found in a context slot.
904   if (index != Context::kNotFound) {
905     if (flag == kNeedsInitialization &&
906         Handle<Context>::cast(holder)->is_the_hole(isolate, index)) {
907       THROW_NEW_ERROR(isolate,
908                       NewReferenceError(MessageTemplate::kNotDefined, name),
909                       Object);
910     }
911     if ((attributes & READ_ONLY) == 0) {
912       Handle<Context>::cast(holder)->set(index, *value);
913     } else if (is_strict(language_mode)) {
914       // Setting read only property in strict mode.
915       THROW_NEW_ERROR(isolate,
916                       NewTypeError(MessageTemplate::kStrictCannotAssign, name),
917                       Object);
918     }
919     return value;
920   }
921 
922   // Slow case: The property is not in a context slot.  It is either in a
923   // context extension object, a property of the subject of a with, or a
924   // property of the global object.
925   Handle<JSReceiver> object;
926   if (attributes != ABSENT) {
927     // The property exists on the holder.
928     object = Handle<JSReceiver>::cast(holder);
929   } else if (is_strict(language_mode)) {
930     // If absent in strict mode: throw.
931     THROW_NEW_ERROR(
932         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
933   } else {
934     // If absent in sloppy mode: add the property to the global object.
935     object = Handle<JSReceiver>(context->global_object());
936   }
937 
938   ASSIGN_RETURN_ON_EXCEPTION(
939       isolate, value, Object::SetProperty(object, name, value, language_mode),
940       Object);
941   return value;
942 }
943 
944 }  // namespace
945 
946 
RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy)947 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Sloppy) {
948   HandleScope scope(isolate);
949   DCHECK_EQ(2, args.length());
950   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
951   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
952   RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, SLOPPY));
953 }
954 
955 
RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict)956 RUNTIME_FUNCTION(Runtime_StoreLookupSlot_Strict) {
957   HandleScope scope(isolate);
958   DCHECK_EQ(2, args.length());
959   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
960   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
961   RETURN_RESULT_OR_FAILURE(isolate, StoreLookupSlot(name, value, STRICT));
962 }
963 
964 }  // namespace internal
965 }  // namespace v8
966