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 "src/accessors.h"
8 #include "src/arguments.h"
9 #include "src/ast/scopeinfo.h"
10 #include "src/ast/scopes.h"
11 #include "src/deoptimizer.h"
12 #include "src/frames-inl.h"
13 #include "src/isolate-inl.h"
14 #include "src/messages.h"
15 
16 namespace v8 {
17 namespace internal {
18 
ThrowRedeclarationError(Isolate * isolate,Handle<String> name)19 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
20   HandleScope scope(isolate);
21   THROW_NEW_ERROR_RETURN_FAILURE(
22       isolate, NewTypeError(MessageTemplate::kVarRedeclaration, name));
23 }
24 
25 
RUNTIME_FUNCTION(Runtime_ThrowConstAssignError)26 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
27   HandleScope scope(isolate);
28   THROW_NEW_ERROR_RETURN_FAILURE(isolate,
29                                  NewTypeError(MessageTemplate::kConstAssign));
30 }
31 
32 
33 // May throw a RedeclarationError.
DeclareGlobals(Isolate * isolate,Handle<JSGlobalObject> global,Handle<String> name,Handle<Object> value,PropertyAttributes attr,bool is_var,bool is_const,bool is_function)34 static Object* DeclareGlobals(Isolate* isolate, Handle<JSGlobalObject> global,
35                               Handle<String> name, Handle<Object> value,
36                               PropertyAttributes attr, bool is_var,
37                               bool is_const, bool is_function) {
38   Handle<ScriptContextTable> script_contexts(
39       global->native_context()->script_context_table());
40   ScriptContextTable::LookupResult lookup;
41   if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
42       IsLexicalVariableMode(lookup.mode)) {
43     return ThrowRedeclarationError(isolate, name);
44   }
45 
46   // Do the lookup own properties only, see ES5 erratum.
47   LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
48   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
49   if (!maybe.IsJust()) return isolate->heap()->exception();
50 
51   if (it.IsFound()) {
52     PropertyAttributes old_attributes = maybe.FromJust();
53     // The name was declared before; check for conflicting re-declarations.
54     if (is_const) return ThrowRedeclarationError(isolate, name);
55 
56     // Skip var re-declarations.
57     if (is_var) return isolate->heap()->undefined_value();
58 
59     DCHECK(is_function);
60     if ((old_attributes & DONT_DELETE) != 0) {
61       // Only allow reconfiguring globals to functions in user code (no
62       // natives, which are marked as read-only).
63       DCHECK((attr & READ_ONLY) == 0);
64 
65       // Check whether we can reconfigure the existing property into a
66       // function.
67       PropertyDetails old_details = it.property_details();
68       // TODO(verwaest): ACCESSOR_CONSTANT invalidly includes
69       // ExecutableAccessInfo,
70       // which are actually data properties, not accessor properties.
71       if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
72           old_details.type() == ACCESSOR_CONSTANT) {
73         return ThrowRedeclarationError(isolate, name);
74       }
75       // If the existing property is not configurable, keep its attributes. Do
76       attr = old_attributes;
77     }
78   }
79 
80   // Define or redefine own property.
81   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
82                                            global, name, value, attr));
83 
84   return isolate->heap()->undefined_value();
85 }
86 
87 
RUNTIME_FUNCTION(Runtime_DeclareGlobals)88 RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
89   HandleScope scope(isolate);
90   DCHECK_EQ(2, args.length());
91   Handle<JSGlobalObject> global(isolate->global_object());
92   Handle<Context> context(isolate->context());
93 
94   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 0);
95   CONVERT_SMI_ARG_CHECKED(flags, 1);
96 
97   // Traverse the name/value pairs and set the properties.
98   int length = pairs->length();
99   for (int i = 0; i < length; i += 2) {
100     HandleScope scope(isolate);
101     Handle<String> name(String::cast(pairs->get(i)));
102     Handle<Object> initial_value(pairs->get(i + 1), isolate);
103 
104     // We have to declare a global const property. To capture we only
105     // assign to it when evaluating the assignment for "const x =
106     // <expr>" the initial value is the hole.
107     bool is_var = initial_value->IsUndefined();
108     bool is_const = initial_value->IsTheHole();
109     bool is_function = initial_value->IsSharedFunctionInfo();
110     DCHECK_EQ(1,
111               BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
112 
113     Handle<Object> value;
114     if (is_function) {
115       // Copy the function and update its context. Use it as value.
116       Handle<SharedFunctionInfo> shared =
117           Handle<SharedFunctionInfo>::cast(initial_value);
118       Handle<JSFunction> function =
119           isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
120                                                                 TENURED);
121       value = function;
122     } else {
123       value = isolate->factory()->undefined_value();
124     }
125 
126     // Compute the property attributes. According to ECMA-262,
127     // the property must be non-configurable except in eval.
128     bool is_native = DeclareGlobalsNativeFlag::decode(flags);
129     bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
130     int attr = NONE;
131     if (is_const) attr |= READ_ONLY;
132     if (is_function && is_native) attr |= READ_ONLY;
133     if (!is_const && !is_eval) attr |= DONT_DELETE;
134 
135     Object* result = DeclareGlobals(isolate, global, name, value,
136                                     static_cast<PropertyAttributes>(attr),
137                                     is_var, is_const, is_function);
138     if (isolate->has_pending_exception()) return result;
139   }
140 
141   return isolate->heap()->undefined_value();
142 }
143 
144 
RUNTIME_FUNCTION(Runtime_InitializeVarGlobal)145 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
146   HandleScope scope(isolate);
147   // args[0] == name
148   // args[1] == language_mode
149   // args[2] == value (optional)
150 
151   // Determine if we need to assign to the variable if it already
152   // exists (based on the number of arguments).
153   RUNTIME_ASSERT(args.length() == 3);
154 
155   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
156   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
157   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
158 
159   Handle<JSGlobalObject> global(isolate->context()->global_object());
160   Handle<Object> result;
161   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
162       isolate, result, Object::SetProperty(global, name, value, language_mode));
163   return *result;
164 }
165 
166 
RUNTIME_FUNCTION(Runtime_InitializeConstGlobal)167 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
168   HandleScope handle_scope(isolate);
169   // All constants are declared with an initial value. The name
170   // of the constant is the first argument and the initial value
171   // is the second.
172   RUNTIME_ASSERT(args.length() == 2);
173   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
174   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
175 
176   Handle<JSGlobalObject> global = isolate->global_object();
177 
178   // Lookup the property as own on the global object.
179   LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
180   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
181   DCHECK(maybe.IsJust());
182   PropertyAttributes old_attributes = maybe.FromJust();
183 
184   PropertyAttributes attr =
185       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
186   // Set the value if the property is either missing, or the property attributes
187   // allow setting the value without invoking an accessor.
188   if (it.IsFound()) {
189     // Ignore if we can't reconfigure the value.
190     if ((old_attributes & DONT_DELETE) != 0) {
191       if ((old_attributes & READ_ONLY) != 0 ||
192           it.state() == LookupIterator::ACCESSOR) {
193         return *value;
194       }
195       attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
196     }
197   }
198 
199   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
200                                            global, name, value, attr));
201 
202   return *value;
203 }
204 
205 
206 namespace {
207 
DeclareLookupSlot(Isolate * isolate,Handle<String> name,Handle<Object> initial_value,PropertyAttributes attr)208 Object* DeclareLookupSlot(Isolate* isolate, Handle<String> name,
209                           Handle<Object> initial_value,
210                           PropertyAttributes attr) {
211   // Declarations are always made in a function, eval or script context, or
212   // a declaration block scope.
213   // In the case of eval code, the context passed is the context of the caller,
214   // which may be some nested context and not the declaration context.
215   Handle<Context> context_arg(isolate->context(), isolate);
216   Handle<Context> context(context_arg->declaration_context(), isolate);
217 
218   // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
219   bool is_var = *initial_value == NULL;
220   bool is_const = initial_value->IsTheHole();
221   bool is_function = initial_value->IsJSFunction();
222   DCHECK_EQ(1,
223             BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
224 
225   int index;
226   PropertyAttributes attributes;
227   BindingFlags binding_flags;
228 
229   if ((attr & EVAL_DECLARED) != 0) {
230     // Check for a conflict with a lexically scoped variable
231     context_arg->Lookup(name, LEXICAL_TEST, &index, &attributes,
232                         &binding_flags);
233     if (attributes != ABSENT &&
234         (binding_flags == MUTABLE_CHECK_INITIALIZED ||
235          binding_flags == IMMUTABLE_CHECK_INITIALIZED ||
236          binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY)) {
237       return ThrowRedeclarationError(isolate, name);
238     }
239     attr = static_cast<PropertyAttributes>(attr & ~EVAL_DECLARED);
240   }
241 
242   Handle<Object> holder = context->Lookup(name, DONT_FOLLOW_CHAINS, &index,
243                                           &attributes, &binding_flags);
244   if (holder.is_null()) {
245     // In case of JSProxy, an exception might have been thrown.
246     if (isolate->has_pending_exception()) return isolate->heap()->exception();
247   }
248 
249   Handle<JSObject> object;
250   Handle<Object> value =
251       is_function ? initial_value
252                   : Handle<Object>::cast(isolate->factory()->undefined_value());
253 
254   // TODO(verwaest): This case should probably not be covered by this function,
255   // but by DeclareGlobals instead.
256   if (attributes != ABSENT && holder->IsJSGlobalObject()) {
257     return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
258                           value, attr, is_var, is_const, is_function);
259   }
260   if (context_arg->extension()->IsJSGlobalObject()) {
261     Handle<JSGlobalObject> global(
262         JSGlobalObject::cast(context_arg->extension()), isolate);
263     return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
264                           is_function);
265   } else if (context->IsScriptContext()) {
266     DCHECK(context->global_object()->IsJSGlobalObject());
267     Handle<JSGlobalObject> global(
268         JSGlobalObject::cast(context->global_object()), isolate);
269     return DeclareGlobals(isolate, global, name, value, attr, is_var, is_const,
270                           is_function);
271   }
272 
273   if (attributes != ABSENT) {
274     // The name was declared before; check for conflicting re-declarations.
275     if (is_const || (attributes & READ_ONLY) != 0) {
276       return ThrowRedeclarationError(isolate, name);
277     }
278 
279     // Skip var re-declarations.
280     if (is_var) return isolate->heap()->undefined_value();
281 
282     DCHECK(is_function);
283     if (index != Context::kNotFound) {
284       DCHECK(holder.is_identical_to(context));
285       context->set(index, *initial_value);
286       return isolate->heap()->undefined_value();
287     }
288 
289     object = Handle<JSObject>::cast(holder);
290 
291   } else if (context->has_extension()) {
292     // Sloppy varblock contexts might not have an extension object yet,
293     // in which case their extension is a ScopeInfo.
294     if (context->extension()->IsScopeInfo()) {
295       DCHECK(context->IsBlockContext());
296       object = isolate->factory()->NewJSObject(
297           isolate->context_extension_function());
298       Handle<HeapObject> extension =
299           isolate->factory()->NewSloppyBlockWithEvalContextExtension(
300               handle(context->scope_info()), object);
301       context->set_extension(*extension);
302     } else {
303       object = handle(context->extension_object(), isolate);
304     }
305     DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
306   } else {
307     DCHECK(context->IsFunctionContext());
308     object =
309         isolate->factory()->NewJSObject(isolate->context_extension_function());
310     context->set_extension(*object);
311   }
312 
313   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
314                                            object, name, value, attr));
315 
316   return isolate->heap()->undefined_value();
317 }
318 
319 }  // namespace
320 
321 
RUNTIME_FUNCTION(Runtime_DeclareLookupSlot)322 RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
323   HandleScope scope(isolate);
324   DCHECK_EQ(3, args.length());
325   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
326   CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 1);
327   CONVERT_ARG_HANDLE_CHECKED(Smi, property_attributes, 2);
328 
329   PropertyAttributes attributes =
330       static_cast<PropertyAttributes>(property_attributes->value());
331   return DeclareLookupSlot(isolate, name, initial_value, attributes);
332 }
333 
334 
RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot)335 RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
336   HandleScope scope(isolate);
337   DCHECK(args.length() == 3);
338 
339   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
340   DCHECK(!value->IsTheHole());
341   // Initializations are always done in a function or native context.
342   CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
343   Handle<Context> context(context_arg->declaration_context());
344   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
345 
346   int index;
347   PropertyAttributes attributes;
348   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
349   BindingFlags binding_flags;
350   Handle<Object> holder =
351       context->Lookup(name, flags, &index, &attributes, &binding_flags);
352   if (holder.is_null()) {
353     // In case of JSProxy, an exception might have been thrown.
354     if (isolate->has_pending_exception()) return isolate->heap()->exception();
355   }
356 
357   if (index != Context::kNotFound) {
358     DCHECK(holder->IsContext());
359     // Property was found in a context.  Perform the assignment if the constant
360     // was uninitialized.
361     Handle<Context> context = Handle<Context>::cast(holder);
362     DCHECK((attributes & READ_ONLY) != 0);
363     if (context->get(index)->IsTheHole()) context->set(index, *value);
364     return *value;
365   }
366 
367   PropertyAttributes attr =
368       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
369 
370   // Strict mode handling not needed (legacy const is disallowed in strict
371   // mode).
372 
373   // The declared const was configurable, and may have been deleted in the
374   // meanwhile. If so, re-introduce the variable in the context extension.
375   if (attributes == ABSENT) {
376     Handle<Context> declaration_context(context_arg->declaration_context());
377     if (declaration_context->IsScriptContext()) {
378       holder = handle(declaration_context->global_object(), isolate);
379     } else {
380       holder = handle(declaration_context->extension_object(), isolate);
381       DCHECK(!holder.is_null());
382     }
383     CHECK(holder->IsJSObject());
384   } else {
385     // For JSContextExtensionObjects, the initializer can be run multiple times
386     // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
387     // first assignment should go through. For JSGlobalObjects, additionally any
388     // code can run in between that modifies the declared property.
389     DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
390 
391     LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
392     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
393     if (!maybe.IsJust()) return isolate->heap()->exception();
394     PropertyAttributes old_attributes = maybe.FromJust();
395 
396     // Ignore if we can't reconfigure the value.
397     if ((old_attributes & DONT_DELETE) != 0) {
398       if ((old_attributes & READ_ONLY) != 0 ||
399           it.state() == LookupIterator::ACCESSOR) {
400         return *value;
401       }
402       attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
403     }
404   }
405 
406   RETURN_FAILURE_ON_EXCEPTION(
407       isolate, JSObject::SetOwnPropertyIgnoreAttributes(
408                    Handle<JSObject>::cast(holder), name, value, attr));
409 
410   return *value;
411 }
412 
413 
414 namespace {
415 
416 // Find the arguments of the JavaScript function invocation that called
417 // into C++ code. Collect these in a newly allocated array of handles (possibly
418 // prefixed by a number of empty handles).
GetCallerArguments(Isolate * isolate,int prefix_argc,int * total_argc)419 base::SmartArrayPointer<Handle<Object>> GetCallerArguments(Isolate* isolate,
420                                                            int prefix_argc,
421                                                            int* total_argc) {
422   // Find frame containing arguments passed to the caller.
423   JavaScriptFrameIterator it(isolate);
424   JavaScriptFrame* frame = it.frame();
425   List<JSFunction*> functions(2);
426   frame->GetFunctions(&functions);
427   if (functions.length() > 1) {
428     int inlined_jsframe_index = functions.length() - 1;
429     TranslatedState translated_values(frame);
430     translated_values.Prepare(false, frame->fp());
431 
432     int argument_count = 0;
433     TranslatedFrame* translated_frame =
434         translated_values.GetArgumentsInfoFromJSFrameIndex(
435             inlined_jsframe_index, &argument_count);
436     TranslatedFrame::iterator iter = translated_frame->begin();
437 
438     // Skip the function.
439     iter++;
440 
441     // Skip the receiver.
442     iter++;
443     argument_count--;
444 
445     *total_argc = prefix_argc + argument_count;
446     base::SmartArrayPointer<Handle<Object>> param_data(
447         NewArray<Handle<Object>>(*total_argc));
448     bool should_deoptimize = false;
449     for (int i = 0; i < argument_count; i++) {
450       should_deoptimize = should_deoptimize || iter->IsMaterializedObject();
451       Handle<Object> value = iter->GetValue();
452       param_data[prefix_argc + i] = value;
453       iter++;
454     }
455 
456     if (should_deoptimize) {
457       translated_values.StoreMaterializedValuesAndDeopt();
458     }
459 
460     return param_data;
461   } else {
462     it.AdvanceToArgumentsFrame();
463     frame = it.frame();
464     int args_count = frame->ComputeParametersCount();
465 
466     *total_argc = prefix_argc + args_count;
467     base::SmartArrayPointer<Handle<Object>> param_data(
468         NewArray<Handle<Object>>(*total_argc));
469     for (int i = 0; i < args_count; i++) {
470       Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
471       param_data[prefix_argc + i] = val;
472     }
473     return param_data;
474   }
475 }
476 
477 
478 template <typename T>
NewSloppyArguments(Isolate * isolate,Handle<JSFunction> callee,T parameters,int argument_count)479 Handle<JSObject> NewSloppyArguments(Isolate* isolate, Handle<JSFunction> callee,
480                                     T parameters, int argument_count) {
481   CHECK(!IsSubclassConstructor(callee->shared()->kind()));
482   DCHECK(callee->shared()->has_simple_parameters());
483   Handle<JSObject> result =
484       isolate->factory()->NewArgumentsObject(callee, argument_count);
485 
486   // Allocate the elements if needed.
487   int parameter_count = callee->shared()->internal_formal_parameter_count();
488   if (argument_count > 0) {
489     if (parameter_count > 0) {
490       int mapped_count = Min(argument_count, parameter_count);
491       Handle<FixedArray> parameter_map =
492           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
493       parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
494       result->set_map(isolate->native_context()->fast_aliased_arguments_map());
495       result->set_elements(*parameter_map);
496 
497       // Store the context and the arguments array at the beginning of the
498       // parameter map.
499       Handle<Context> context(isolate->context());
500       Handle<FixedArray> arguments =
501           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
502       parameter_map->set(0, *context);
503       parameter_map->set(1, *arguments);
504 
505       // Loop over the actual parameters backwards.
506       int index = argument_count - 1;
507       while (index >= mapped_count) {
508         // These go directly in the arguments array and have no
509         // corresponding slot in the parameter map.
510         arguments->set(index, parameters[index]);
511         --index;
512       }
513 
514       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
515       while (index >= 0) {
516         // Detect duplicate names to the right in the parameter list.
517         Handle<String> name(scope_info->ParameterName(index));
518         int context_local_count = scope_info->ContextLocalCount();
519         bool duplicate = false;
520         for (int j = index + 1; j < parameter_count; ++j) {
521           if (scope_info->ParameterName(j) == *name) {
522             duplicate = true;
523             break;
524           }
525         }
526 
527         if (duplicate) {
528           // This goes directly in the arguments array with a hole in the
529           // parameter map.
530           arguments->set(index, parameters[index]);
531           parameter_map->set_the_hole(index + 2);
532         } else {
533           // The context index goes in the parameter map with a hole in the
534           // arguments array.
535           int context_index = -1;
536           for (int j = 0; j < context_local_count; ++j) {
537             if (scope_info->ContextLocalName(j) == *name) {
538               context_index = j;
539               break;
540             }
541           }
542 
543           DCHECK(context_index >= 0);
544           arguments->set_the_hole(index);
545           parameter_map->set(
546               index + 2,
547               Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
548         }
549 
550         --index;
551       }
552     } else {
553       // If there is no aliasing, the arguments object elements are not
554       // special in any way.
555       Handle<FixedArray> elements =
556           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
557       result->set_elements(*elements);
558       for (int i = 0; i < argument_count; ++i) {
559         elements->set(i, parameters[i]);
560       }
561     }
562   }
563   return result;
564 }
565 
566 
567 template <typename T>
NewStrictArguments(Isolate * isolate,Handle<JSFunction> callee,T parameters,int argument_count)568 Handle<JSObject> NewStrictArguments(Isolate* isolate, Handle<JSFunction> callee,
569                                     T parameters, int argument_count) {
570   Handle<JSObject> result =
571       isolate->factory()->NewArgumentsObject(callee, argument_count);
572 
573   if (argument_count > 0) {
574     Handle<FixedArray> array =
575         isolate->factory()->NewUninitializedFixedArray(argument_count);
576     DisallowHeapAllocation no_gc;
577     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
578     for (int i = 0; i < argument_count; i++) {
579       array->set(i, parameters[i], mode);
580     }
581     result->set_elements(*array);
582   }
583   return result;
584 }
585 
586 
587 template <typename T>
NewRestArguments(Isolate * isolate,Handle<JSFunction> callee,T parameters,int argument_count,int start_index)588 Handle<JSObject> NewRestArguments(Isolate* isolate, Handle<JSFunction> callee,
589                                   T parameters, int argument_count,
590                                   int start_index) {
591   int num_elements = std::max(0, argument_count - start_index);
592   Handle<JSObject> result = isolate->factory()->NewJSArray(
593       FAST_ELEMENTS, num_elements, num_elements, Strength::WEAK,
594       DONT_INITIALIZE_ARRAY_ELEMENTS);
595   {
596     DisallowHeapAllocation no_gc;
597     FixedArray* elements = FixedArray::cast(result->elements());
598     WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
599     for (int i = 0; i < num_elements; i++) {
600       elements->set(i, parameters[i + start_index], mode);
601     }
602   }
603   return result;
604 }
605 
606 
607 class HandleArguments BASE_EMBEDDED {
608  public:
HandleArguments(Handle<Object> * array)609   explicit HandleArguments(Handle<Object>* array) : array_(array) {}
operator [](int index)610   Object* operator[](int index) { return *array_[index]; }
611 
612  private:
613   Handle<Object>* array_;
614 };
615 
616 
617 class ParameterArguments BASE_EMBEDDED {
618  public:
ParameterArguments(Object ** parameters)619   explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
operator [](int index)620   Object*& operator[](int index) { return *(parameters_ - index - 1); }
621 
622  private:
623   Object** parameters_;
624 };
625 
626 }  // namespace
627 
628 
RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic)629 RUNTIME_FUNCTION(Runtime_NewSloppyArguments_Generic) {
630   HandleScope scope(isolate);
631   DCHECK(args.length() == 1);
632   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
633   // This generic runtime function can also be used when the caller has been
634   // inlined, we use the slow but accurate {GetCallerArguments}.
635   int argument_count = 0;
636   base::SmartArrayPointer<Handle<Object>> arguments =
637       GetCallerArguments(isolate, 0, &argument_count);
638   HandleArguments argument_getter(arguments.get());
639   return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
640 }
641 
642 
RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic)643 RUNTIME_FUNCTION(Runtime_NewStrictArguments_Generic) {
644   HandleScope scope(isolate);
645   DCHECK(args.length() == 1);
646   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
647   // This generic runtime function can also be used when the caller has been
648   // inlined, we use the slow but accurate {GetCallerArguments}.
649   int argument_count = 0;
650   base::SmartArrayPointer<Handle<Object>> arguments =
651       GetCallerArguments(isolate, 0, &argument_count);
652   HandleArguments argument_getter(arguments.get());
653   return *NewStrictArguments(isolate, callee, argument_getter, argument_count);
654 }
655 
656 
RUNTIME_FUNCTION(Runtime_NewRestArguments_Generic)657 RUNTIME_FUNCTION(Runtime_NewRestArguments_Generic) {
658   HandleScope scope(isolate);
659   DCHECK(args.length() == 2);
660   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
661   CONVERT_SMI_ARG_CHECKED(start_index, 1);
662   // This generic runtime function can also be used when the caller has been
663   // inlined, we use the slow but accurate {GetCallerArguments}.
664   int argument_count = 0;
665   base::SmartArrayPointer<Handle<Object>> arguments =
666       GetCallerArguments(isolate, 0, &argument_count);
667   HandleArguments argument_getter(arguments.get());
668   return *NewRestArguments(isolate, callee, argument_getter, argument_count,
669                            start_index);
670 }
671 
672 
RUNTIME_FUNCTION(Runtime_NewSloppyArguments)673 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
674   HandleScope scope(isolate);
675   DCHECK(args.length() == 3);
676   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
677   Object** parameters = reinterpret_cast<Object**>(args[1]);
678   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
679 #ifdef DEBUG
680   // This runtime function does not materialize the correct arguments when the
681   // caller has been inlined, better make sure we are not hitting that case.
682   JavaScriptFrameIterator it(isolate);
683   DCHECK(!it.frame()->HasInlinedFrames());
684 #endif  // DEBUG
685   ParameterArguments argument_getter(parameters);
686   return *NewSloppyArguments(isolate, callee, argument_getter, argument_count);
687 }
688 
689 
RUNTIME_FUNCTION(Runtime_NewStrictArguments)690 RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
691   HandleScope scope(isolate);
692   DCHECK(args.length() == 3);
693   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
694   Object** parameters = reinterpret_cast<Object**>(args[1]);
695   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
696 #ifdef DEBUG
697   // This runtime function does not materialize the correct arguments when the
698   // caller has been inlined, better make sure we are not hitting that case.
699   JavaScriptFrameIterator it(isolate);
700   DCHECK(!it.frame()->HasInlinedFrames());
701 #endif  // DEBUG
702   ParameterArguments argument_getter(parameters);
703   return *NewStrictArguments(isolate, callee, argument_getter, argument_count);
704 }
705 
706 
RUNTIME_FUNCTION(Runtime_NewRestParam)707 RUNTIME_FUNCTION(Runtime_NewRestParam) {
708   HandleScope scope(isolate);
709   DCHECK(args.length() == 3);
710   CONVERT_SMI_ARG_CHECKED(num_params, 0);
711   Object** parameters = reinterpret_cast<Object**>(args[1]);
712   CONVERT_SMI_ARG_CHECKED(rest_index, 2);
713 #ifdef DEBUG
714   // This runtime function does not materialize the correct arguments when the
715   // caller has been inlined, better make sure we are not hitting that case.
716   JavaScriptFrameIterator it(isolate);
717   DCHECK(!it.frame()->HasInlinedFrames());
718 #endif  // DEBUG
719   Handle<JSFunction> callee;
720   ParameterArguments argument_getter(parameters);
721   return *NewRestArguments(isolate, callee, argument_getter, num_params,
722                            rest_index);
723 }
724 
725 
RUNTIME_FUNCTION(Runtime_NewClosure)726 RUNTIME_FUNCTION(Runtime_NewClosure) {
727   HandleScope scope(isolate);
728   DCHECK_EQ(1, args.length());
729   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
730   Handle<Context> context(isolate->context(), isolate);
731   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
732                                                                 NOT_TENURED);
733 }
734 
735 
RUNTIME_FUNCTION(Runtime_NewClosure_Tenured)736 RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
737   HandleScope scope(isolate);
738   DCHECK_EQ(1, args.length());
739   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
740   Handle<Context> context(isolate->context(), isolate);
741   // The caller ensures that we pretenure closures that are assigned
742   // directly to properties.
743   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
744                                                                 TENURED);
745 }
746 
FindNameClash(Handle<ScopeInfo> scope_info,Handle<JSGlobalObject> global_object,Handle<ScriptContextTable> script_context)747 static Object* FindNameClash(Handle<ScopeInfo> scope_info,
748                              Handle<JSGlobalObject> global_object,
749                              Handle<ScriptContextTable> script_context) {
750   Isolate* isolate = scope_info->GetIsolate();
751   for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
752     Handle<String> name(scope_info->ContextLocalName(var));
753     VariableMode mode = scope_info->ContextLocalMode(var);
754     ScriptContextTable::LookupResult lookup;
755     if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
756       if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
757         return ThrowRedeclarationError(isolate, name);
758       }
759     }
760 
761     if (IsLexicalVariableMode(mode)) {
762       LookupIterator it(global_object, name,
763                         LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
764       Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
765       if (!maybe.IsJust()) return isolate->heap()->exception();
766       if ((maybe.FromJust() & DONT_DELETE) != 0) {
767         return ThrowRedeclarationError(isolate, name);
768       }
769 
770       JSGlobalObject::InvalidatePropertyCell(global_object, name);
771     }
772   }
773   return isolate->heap()->undefined_value();
774 }
775 
776 
RUNTIME_FUNCTION(Runtime_NewScriptContext)777 RUNTIME_FUNCTION(Runtime_NewScriptContext) {
778   HandleScope scope(isolate);
779   DCHECK(args.length() == 2);
780 
781   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
782   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
783   Handle<JSGlobalObject> global_object(function->context()->global_object());
784   Handle<Context> native_context(global_object->native_context());
785   Handle<ScriptContextTable> script_context_table(
786       native_context->script_context_table());
787 
788   Object* name_clash_result =
789       FindNameClash(scope_info, global_object, script_context_table);
790   if (isolate->has_pending_exception()) return name_clash_result;
791 
792   // Script contexts have a canonical empty function as their closure, not the
793   // anonymous closure containing the global code.  See
794   // FullCodeGenerator::PushFunctionArgumentForContextAllocation.
795   Handle<JSFunction> closure(
796       function->shared()->IsBuiltin() ? *function : native_context->closure());
797   Handle<Context> result =
798       isolate->factory()->NewScriptContext(closure, scope_info);
799 
800   result->InitializeGlobalSlots();
801 
802   DCHECK(function->context() == isolate->context());
803   DCHECK(*global_object == result->global_object());
804 
805   Handle<ScriptContextTable> new_script_context_table =
806       ScriptContextTable::Extend(script_context_table, result);
807   native_context->set_script_context_table(*new_script_context_table);
808   return *result;
809 }
810 
811 
RUNTIME_FUNCTION(Runtime_NewFunctionContext)812 RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
813   HandleScope scope(isolate);
814   DCHECK(args.length() == 1);
815 
816   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
817 
818   DCHECK(function->context() == isolate->context());
819   int length = function->shared()->scope_info()->ContextLength();
820   return *isolate->factory()->NewFunctionContext(length, function);
821 }
822 
823 
RUNTIME_FUNCTION(Runtime_PushWithContext)824 RUNTIME_FUNCTION(Runtime_PushWithContext) {
825   HandleScope scope(isolate);
826   DCHECK_EQ(2, args.length());
827   CONVERT_ARG_HANDLE_CHECKED(JSReceiver, extension_object, 0);
828   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
829   Handle<Context> current(isolate->context());
830   Handle<Context> context =
831       isolate->factory()->NewWithContext(function, current, extension_object);
832   isolate->set_context(*context);
833   return *context;
834 }
835 
836 
RUNTIME_FUNCTION(Runtime_PushCatchContext)837 RUNTIME_FUNCTION(Runtime_PushCatchContext) {
838   HandleScope scope(isolate);
839   DCHECK_EQ(3, args.length());
840   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
841   CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
842   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 2);
843   Handle<Context> current(isolate->context());
844   Handle<Context> context = isolate->factory()->NewCatchContext(
845       function, current, name, thrown_object);
846   isolate->set_context(*context);
847   return *context;
848 }
849 
850 
RUNTIME_FUNCTION(Runtime_PushBlockContext)851 RUNTIME_FUNCTION(Runtime_PushBlockContext) {
852   HandleScope scope(isolate);
853   DCHECK_EQ(2, args.length());
854   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
855   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
856   Handle<Context> current(isolate->context());
857   Handle<Context> context =
858       isolate->factory()->NewBlockContext(function, current, scope_info);
859   isolate->set_context(*context);
860   return *context;
861 }
862 
863 
RUNTIME_FUNCTION(Runtime_IsJSModule)864 RUNTIME_FUNCTION(Runtime_IsJSModule) {
865   SealHandleScope shs(isolate);
866   DCHECK(args.length() == 1);
867   CONVERT_ARG_CHECKED(Object, obj, 0);
868   return isolate->heap()->ToBoolean(obj->IsJSModule());
869 }
870 
871 
RUNTIME_FUNCTION(Runtime_PushModuleContext)872 RUNTIME_FUNCTION(Runtime_PushModuleContext) {
873   SealHandleScope shs(isolate);
874   DCHECK(args.length() == 2);
875   CONVERT_SMI_ARG_CHECKED(index, 0);
876 
877   if (!args[1]->IsScopeInfo()) {
878     // Module already initialized. Find hosting context and retrieve context.
879     Context* host = Context::cast(isolate->context())->script_context();
880     Context* context = Context::cast(host->get(index));
881     DCHECK(context->previous() == isolate->context());
882     isolate->set_context(context);
883     return context;
884   }
885 
886   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
887 
888   // Allocate module context.
889   HandleScope scope(isolate);
890   Factory* factory = isolate->factory();
891   Handle<Context> context = factory->NewModuleContext(scope_info);
892   Handle<JSModule> module = factory->NewJSModule(context, scope_info);
893   context->set_module(*module);
894   Context* previous = isolate->context();
895   context->set_previous(previous);
896   context->set_closure(previous->closure());
897   context->set_native_context(previous->native_context());
898   isolate->set_context(*context);
899 
900   // Find hosting scope and initialize internal variable holding module there.
901   previous->script_context()->set(index, *context);
902 
903   return *context;
904 }
905 
906 
RUNTIME_FUNCTION(Runtime_DeclareModules)907 RUNTIME_FUNCTION(Runtime_DeclareModules) {
908   HandleScope scope(isolate);
909   DCHECK(args.length() == 1);
910   CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
911   Context* host_context = isolate->context();
912 
913   for (int i = 0; i < descriptions->length(); ++i) {
914     Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
915     int host_index = description->host_index();
916     Handle<Context> context(Context::cast(host_context->get(host_index)));
917     Handle<JSModule> module(context->module());
918 
919     for (int j = 0; j < description->length(); ++j) {
920       Handle<String> name(description->name(j));
921       VariableMode mode = description->mode(j);
922       int index = description->index(j);
923       switch (mode) {
924         case VAR:
925         case LET:
926         case CONST:
927         case CONST_LEGACY:
928         case IMPORT: {
929           PropertyAttributes attr =
930               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
931           Handle<AccessorInfo> info =
932               Accessors::MakeModuleExport(name, index, attr);
933           Handle<Object> result =
934               JSObject::SetAccessor(module, info).ToHandleChecked();
935           DCHECK(!result->IsUndefined());
936           USE(result);
937           break;
938         }
939         case TEMPORARY:
940         case DYNAMIC:
941         case DYNAMIC_GLOBAL:
942         case DYNAMIC_LOCAL:
943           UNREACHABLE();
944       }
945     }
946 
947     if (JSObject::PreventExtensions(module, Object::THROW_ON_ERROR)
948             .IsNothing()) {
949       DCHECK(false);
950     }
951   }
952 
953   DCHECK(!isolate->has_pending_exception());
954   return isolate->heap()->undefined_value();
955 }
956 
957 
RUNTIME_FUNCTION(Runtime_DeleteLookupSlot)958 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
959   HandleScope scope(isolate);
960   DCHECK(args.length() == 2);
961 
962   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
963   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
964 
965   int index;
966   PropertyAttributes attributes;
967   ContextLookupFlags flags = FOLLOW_CHAINS;
968   BindingFlags binding_flags;
969   Handle<Object> holder =
970       context->Lookup(name, flags, &index, &attributes, &binding_flags);
971 
972   // If the slot was not found the result is true.
973   if (holder.is_null()) {
974     // In case of JSProxy, an exception might have been thrown.
975     if (isolate->has_pending_exception()) return isolate->heap()->exception();
976     return isolate->heap()->true_value();
977   }
978 
979   // If the slot was found in a context, it should be DONT_DELETE.
980   if (holder->IsContext()) {
981     return isolate->heap()->false_value();
982   }
983 
984   // The slot was found in a JSReceiver, either a context extension object,
985   // the global object, or the subject of a with.  Try to delete it
986   // (respecting DONT_DELETE).
987   Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
988   Maybe<bool> result = JSReceiver::DeleteProperty(object, name);
989   MAYBE_RETURN(result, isolate->heap()->exception());
990   return isolate->heap()->ToBoolean(result.FromJust());
991 }
992 
993 
ComputeReceiverForNonGlobal(Isolate * isolate,JSObject * holder)994 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) {
995   DCHECK(!holder->IsJSGlobalObject());
996 
997   // If the holder isn't a context extension object, we just return it
998   // as the receiver. This allows arguments objects to be used as
999   // receivers, but only if they are put in the context scope chain
1000   // explicitly via a with-statement.
1001   if (holder->map()->instance_type() != JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
1002     return holder;
1003   }
1004   // Fall back to using the global object as the implicit receiver if
1005   // the property turns out to be a local variable allocated in a
1006   // context extension object - introduced via eval.
1007   return isolate->heap()->undefined_value();
1008 }
1009 
1010 
LoadLookupSlotHelper(Arguments args,Isolate * isolate,bool throw_error)1011 static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate,
1012                                        bool throw_error) {
1013   HandleScope scope(isolate);
1014   DCHECK_EQ(2, args.length());
1015 
1016   if (!args[0]->IsContext() || !args[1]->IsString()) {
1017     return MakePair(isolate->ThrowIllegalOperation(), NULL);
1018   }
1019   Handle<Context> context = args.at<Context>(0);
1020   Handle<String> name = args.at<String>(1);
1021 
1022   int index;
1023   PropertyAttributes attributes;
1024   ContextLookupFlags flags = FOLLOW_CHAINS;
1025   BindingFlags binding_flags;
1026   Handle<Object> holder =
1027       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1028   if (isolate->has_pending_exception()) {
1029     return MakePair(isolate->heap()->exception(), NULL);
1030   }
1031 
1032   if (index != Context::kNotFound) {
1033     DCHECK(holder->IsContext());
1034     // If the "property" we were looking for is a local variable, the
1035     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
1036     Handle<Object> receiver = isolate->factory()->undefined_value();
1037     Object* value = Context::cast(*holder)->get(index);
1038     // Check for uninitialized bindings.
1039     switch (binding_flags) {
1040       case MUTABLE_CHECK_INITIALIZED:
1041       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
1042         if (value->IsTheHole()) {
1043           Handle<Object> error = isolate->factory()->NewReferenceError(
1044               MessageTemplate::kNotDefined, name);
1045           isolate->Throw(*error);
1046           return MakePair(isolate->heap()->exception(), NULL);
1047         }
1048       // FALLTHROUGH
1049       case MUTABLE_IS_INITIALIZED:
1050       case IMMUTABLE_IS_INITIALIZED:
1051       case IMMUTABLE_IS_INITIALIZED_HARMONY:
1052         DCHECK(!value->IsTheHole());
1053         return MakePair(value, *receiver);
1054       case IMMUTABLE_CHECK_INITIALIZED:
1055         if (value->IsTheHole()) {
1056           DCHECK((attributes & READ_ONLY) != 0);
1057           value = isolate->heap()->undefined_value();
1058         }
1059         return MakePair(value, *receiver);
1060       case MISSING_BINDING:
1061         UNREACHABLE();
1062         return MakePair(NULL, NULL);
1063     }
1064   }
1065 
1066   // Otherwise, if the slot was found the holder is a context extension
1067   // object, subject of a with, or a global object.  We read the named
1068   // property from it.
1069   if (!holder.is_null()) {
1070     Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
1071     // GetProperty below can cause GC.
1072     Handle<Object> receiver_handle(
1073         object->IsJSGlobalObject()
1074             ? Object::cast(isolate->heap()->undefined_value())
1075             : object->IsJSProxy() ? static_cast<Object*>(*object)
1076                                   : ComputeReceiverForNonGlobal(
1077                                         isolate, JSObject::cast(*object)),
1078         isolate);
1079 
1080     // No need to unhole the value here.  This is taken care of by the
1081     // GetProperty function.
1082     Handle<Object> value;
1083     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1084         isolate, value, Object::GetProperty(object, name),
1085         MakePair(isolate->heap()->exception(), NULL));
1086     return MakePair(*value, *receiver_handle);
1087   }
1088 
1089   if (throw_error) {
1090     // The property doesn't exist - throw exception.
1091     Handle<Object> error = isolate->factory()->NewReferenceError(
1092         MessageTemplate::kNotDefined, name);
1093     isolate->Throw(*error);
1094     return MakePair(isolate->heap()->exception(), NULL);
1095   } else {
1096     // The property doesn't exist - return undefined.
1097     return MakePair(isolate->heap()->undefined_value(),
1098                     isolate->heap()->undefined_value());
1099   }
1100 }
1101 
1102 
RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot)1103 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) {
1104   return LoadLookupSlotHelper(args, isolate, true);
1105 }
1106 
1107 
RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError)1108 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) {
1109   return LoadLookupSlotHelper(args, isolate, false);
1110 }
1111 
1112 
RUNTIME_FUNCTION(Runtime_StoreLookupSlot)1113 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
1114   HandleScope scope(isolate);
1115   DCHECK(args.length() == 4);
1116 
1117   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
1118   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
1119   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
1120   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
1121 
1122   int index;
1123   PropertyAttributes attributes;
1124   ContextLookupFlags flags = FOLLOW_CHAINS;
1125   BindingFlags binding_flags;
1126   Handle<Object> holder =
1127       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1128   if (holder.is_null()) {
1129     // In case of JSProxy, an exception might have been thrown.
1130     if (isolate->has_pending_exception()) return isolate->heap()->exception();
1131   }
1132 
1133   // The property was found in a context slot.
1134   if (index != Context::kNotFound) {
1135     if ((binding_flags == MUTABLE_CHECK_INITIALIZED ||
1136          binding_flags == IMMUTABLE_CHECK_INITIALIZED_HARMONY) &&
1137         Handle<Context>::cast(holder)->is_the_hole(index)) {
1138       THROW_NEW_ERROR_RETURN_FAILURE(
1139           isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
1140     }
1141     if ((attributes & READ_ONLY) == 0) {
1142       Handle<Context>::cast(holder)->set(index, *value);
1143     } else if (is_strict(language_mode)) {
1144       // Setting read only property in strict mode.
1145       THROW_NEW_ERROR_RETURN_FAILURE(
1146           isolate, NewTypeError(MessageTemplate::kStrictCannotAssign, name));
1147     }
1148     return *value;
1149   }
1150 
1151   // Slow case: The property is not in a context slot.  It is either in a
1152   // context extension object, a property of the subject of a with, or a
1153   // property of the global object.
1154   Handle<JSReceiver> object;
1155   if (attributes != ABSENT) {
1156     // The property exists on the holder.
1157     object = Handle<JSReceiver>::cast(holder);
1158   } else if (is_strict(language_mode)) {
1159     // If absent in strict mode: throw.
1160     THROW_NEW_ERROR_RETURN_FAILURE(
1161         isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
1162   } else {
1163     // If absent in sloppy mode: add the property to the global object.
1164     object = Handle<JSReceiver>(context->global_object());
1165   }
1166 
1167   RETURN_FAILURE_ON_EXCEPTION(
1168       isolate, Object::SetProperty(object, name, value, language_mode));
1169 
1170   return *value;
1171 }
1172 
1173 
RUNTIME_FUNCTION(Runtime_ArgumentsLength)1174 RUNTIME_FUNCTION(Runtime_ArgumentsLength) {
1175   HandleScope scope(isolate);
1176   DCHECK(args.length() == 0);
1177   int argument_count = 0;
1178   GetCallerArguments(isolate, 0, &argument_count);
1179   return Smi::FromInt(argument_count);
1180 }
1181 
1182 
RUNTIME_FUNCTION(Runtime_Arguments)1183 RUNTIME_FUNCTION(Runtime_Arguments) {
1184   HandleScope scope(isolate);
1185   DCHECK(args.length() == 1);
1186   CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
1187 
1188   // Determine the actual arguments passed to the function.
1189   int argument_count_signed = 0;
1190   base::SmartArrayPointer<Handle<Object>> arguments =
1191       GetCallerArguments(isolate, 0, &argument_count_signed);
1192   const uint32_t argument_count = argument_count_signed;
1193 
1194   // Try to convert the key to an index. If successful and within
1195   // index return the the argument from the frame.
1196   uint32_t index = 0;
1197   if (raw_key->ToArrayIndex(&index) && index < argument_count) {
1198     return *arguments[index];
1199   }
1200 
1201   if (raw_key->IsSymbol()) {
1202     Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
1203     if (Name::Equals(symbol, isolate->factory()->iterator_symbol())) {
1204       return isolate->native_context()->array_values_iterator();
1205     }
1206     // Lookup in the initial Object.prototype object.
1207     Handle<Object> result;
1208     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1209         isolate, result,
1210         Object::GetProperty(isolate->initial_object_prototype(),
1211                             Handle<Symbol>::cast(raw_key)));
1212     return *result;
1213   }
1214 
1215   // Convert the key to a string.
1216   Handle<Object> converted;
1217   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, converted,
1218                                      Object::ToString(isolate, raw_key));
1219   Handle<String> key = Handle<String>::cast(converted);
1220 
1221   // Try to convert the string key into an array index.
1222   if (key->AsArrayIndex(&index)) {
1223     if (index < argument_count) {
1224       return *arguments[index];
1225     } else {
1226       Handle<Object> initial_prototype(isolate->initial_object_prototype());
1227       Handle<Object> result;
1228       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1229           isolate, result,
1230           Object::GetElement(isolate, initial_prototype, index));
1231       return *result;
1232     }
1233   }
1234 
1235   // Handle special arguments properties.
1236   if (String::Equals(isolate->factory()->length_string(), key)) {
1237     return Smi::FromInt(argument_count);
1238   }
1239   if (String::Equals(isolate->factory()->callee_string(), key)) {
1240     JavaScriptFrameIterator it(isolate);
1241     JSFunction* function = it.frame()->function();
1242     if (is_strict(function->shared()->language_mode())) {
1243       THROW_NEW_ERROR_RETURN_FAILURE(
1244           isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
1245     }
1246     return function;
1247   }
1248 
1249   // Lookup in the initial Object.prototype object.
1250   Handle<Object> result;
1251   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1252       isolate, result,
1253       Object::GetProperty(isolate->initial_object_prototype(), key));
1254   return *result;
1255 }
1256 }  // namespace internal
1257 }  // namespace v8
1258