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
16namespace v8 {
17namespace internal {
18
19static 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
26RUNTIME_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.
34static 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
88RUNTIME_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
145RUNTIME_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
167RUNTIME_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
206namespace {
207
208Object* 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
322RUNTIME_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
335RUNTIME_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
414namespace {
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).
419base::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
478template <typename T>
479Handle<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
567template <typename T>
568Handle<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
587template <typename T>
588Handle<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
607class HandleArguments BASE_EMBEDDED {
608 public:
609  explicit HandleArguments(Handle<Object>* array) : array_(array) {}
610  Object* operator[](int index) { return *array_[index]; }
611
612 private:
613  Handle<Object>* array_;
614};
615
616
617class ParameterArguments BASE_EMBEDDED {
618 public:
619  explicit ParameterArguments(Object** parameters) : parameters_(parameters) {}
620  Object*& operator[](int index) { return *(parameters_ - index - 1); }
621
622 private:
623  Object** parameters_;
624};
625
626}  // namespace
627
628
629RUNTIME_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
643RUNTIME_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
657RUNTIME_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
673RUNTIME_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
690RUNTIME_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
707RUNTIME_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
726RUNTIME_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
736RUNTIME_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
747static 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
777RUNTIME_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
812RUNTIME_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
824RUNTIME_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
837RUNTIME_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
851RUNTIME_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
864RUNTIME_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
872RUNTIME_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
907RUNTIME_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
958RUNTIME_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
994static 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
1011static 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
1103RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) {
1104  return LoadLookupSlotHelper(args, isolate, true);
1105}
1106
1107
1108RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) {
1109  return LoadLookupSlotHelper(args, isolate, false);
1110}
1111
1112
1113RUNTIME_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
1174RUNTIME_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
1183RUNTIME_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