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