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