7eb2e0cfc1703940ec9e5a0231a17248b7df3d15
[platform/upstream/nodejs.git] / deps / v8 / src / runtime / runtime-scopes.cc
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/v8.h"
6
7 #include "src/accessors.h"
8 #include "src/arguments.h"
9 #include "src/frames-inl.h"
10 #include "src/runtime/runtime-utils.h"
11 #include "src/scopeinfo.h"
12 #include "src/scopes.h"
13
14 namespace v8 {
15 namespace internal {
16
17 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
18   HandleScope scope(isolate);
19   Handle<Object> args[1] = {name};
20   THROW_NEW_ERROR_RETURN_FAILURE(
21       isolate, NewTypeError("var_redeclaration", HandleVector(args, 1)));
22 }
23
24
25 RUNTIME_FUNCTION(Runtime_ThrowConstAssignError) {
26   HandleScope scope(isolate);
27   THROW_NEW_ERROR_RETURN_FAILURE(
28       isolate,
29       NewTypeError("harmony_const_assign", HandleVector<Object>(NULL, 0)));
30 }
31
32
33 // May throw a RedeclarationError.
34 static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> 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.has_value) return isolate->heap()->exception();
50
51   if (it.IsFound()) {
52     PropertyAttributes old_attributes = maybe.value;
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
88 RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
89   HandleScope scope(isolate);
90   DCHECK(args.length() == 3);
91   Handle<GlobalObject> global(isolate->global_object());
92
93   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
94   CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
95   CONVERT_SMI_ARG_CHECKED(flags, 2);
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
145 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
146   HandleScope scope(isolate);
147   // args[0] == name
148   // args[1] == language_mode
149   // args[2] == value (optional)
150
151   // Determine if we need to assign to the variable if it already
152   // exists (based on the number of arguments).
153   RUNTIME_ASSERT(args.length() == 3);
154
155   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
156   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 1);
157   CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
158
159   Handle<GlobalObject> 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
167 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
168   HandleScope handle_scope(isolate);
169   // All constants are declared with an initial value. The name
170   // of the constant is the first argument and the initial value
171   // is the second.
172   RUNTIME_ASSERT(args.length() == 2);
173   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
174   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
175
176   Handle<GlobalObject> 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.has_value);
182   PropertyAttributes old_attributes = maybe.value;
183
184   PropertyAttributes attr =
185       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
186   // Set the value if the property is either missing, or the property attributes
187   // allow setting the value without invoking an accessor.
188   if (it.IsFound()) {
189     // Ignore if we can't reconfigure the value.
190     if ((old_attributes & DONT_DELETE) != 0) {
191       if ((old_attributes & READ_ONLY) != 0 ||
192           it.state() == LookupIterator::ACCESSOR) {
193         return *value;
194       }
195       attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
196     }
197   }
198
199   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
200                                            global, name, value, attr));
201
202   return *value;
203 }
204
205
206 RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
207   HandleScope scope(isolate);
208   DCHECK(args.length() == 4);
209
210   // Declarations are always made in a function, eval or script context. In
211   // the case of eval code, the context passed is the context of the caller,
212   // which may be some nested context and not the declaration context.
213   CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
214   Handle<Context> context(context_arg->declaration_context());
215   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
216   CONVERT_SMI_ARG_CHECKED(attr_arg, 2);
217   PropertyAttributes attr = static_cast<PropertyAttributes>(attr_arg);
218   RUNTIME_ASSERT(attr == READ_ONLY || attr == NONE);
219   CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
220
221   // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
222   bool is_var = *initial_value == NULL;
223   bool is_const = initial_value->IsTheHole();
224   bool is_function = initial_value->IsJSFunction();
225   DCHECK_EQ(1,
226             BoolToInt(is_var) + BoolToInt(is_const) + BoolToInt(is_function));
227
228   int index;
229   PropertyAttributes attributes;
230   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
231   BindingFlags binding_flags;
232   Handle<Object> holder =
233       context->Lookup(name, flags, &index, &attributes, &binding_flags);
234
235   Handle<JSObject> object;
236   Handle<Object> value =
237       is_function ? initial_value
238                   : Handle<Object>::cast(isolate->factory()->undefined_value());
239
240   // TODO(verwaest): This case should probably not be covered by this function,
241   // but by DeclareGlobals instead.
242   if ((attributes != ABSENT && holder->IsJSGlobalObject()) ||
243       (context_arg->has_extension() &&
244        context_arg->extension()->IsJSGlobalObject())) {
245     return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
246                           value, attr, is_var, is_const, is_function);
247   }
248
249   if (attributes != ABSENT) {
250     // The name was declared before; check for conflicting re-declarations.
251     if (is_const || (attributes & READ_ONLY) != 0) {
252       return ThrowRedeclarationError(isolate, name);
253     }
254
255     // Skip var re-declarations.
256     if (is_var) return isolate->heap()->undefined_value();
257
258     DCHECK(is_function);
259     if (index >= 0) {
260       DCHECK(holder.is_identical_to(context));
261       context->set(index, *initial_value);
262       return isolate->heap()->undefined_value();
263     }
264
265     object = Handle<JSObject>::cast(holder);
266
267   } else if (context->has_extension()) {
268     object = handle(JSObject::cast(context->extension()));
269     DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
270   } else {
271     DCHECK(context->IsFunctionContext());
272     object =
273         isolate->factory()->NewJSObject(isolate->context_extension_function());
274     context->set_extension(*object);
275   }
276
277   RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
278                                            object, name, value, attr));
279
280   return isolate->heap()->undefined_value();
281 }
282
283
284 RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
285   HandleScope scope(isolate);
286   DCHECK(args.length() == 3);
287
288   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
289   DCHECK(!value->IsTheHole());
290   // Initializations are always done in a function or native context.
291   CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
292   Handle<Context> context(context_arg->declaration_context());
293   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
294
295   int index;
296   PropertyAttributes attributes;
297   ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
298   BindingFlags binding_flags;
299   Handle<Object> holder =
300       context->Lookup(name, flags, &index, &attributes, &binding_flags);
301
302   if (index >= 0) {
303     DCHECK(holder->IsContext());
304     // Property was found in a context.  Perform the assignment if the constant
305     // was uninitialized.
306     Handle<Context> context = Handle<Context>::cast(holder);
307     DCHECK((attributes & READ_ONLY) != 0);
308     if (context->get(index)->IsTheHole()) context->set(index, *value);
309     return *value;
310   }
311
312   PropertyAttributes attr =
313       static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
314
315   // Strict mode handling not needed (legacy const is disallowed in strict
316   // mode).
317
318   // The declared const was configurable, and may have been deleted in the
319   // meanwhile. If so, re-introduce the variable in the context extension.
320   if (attributes == ABSENT) {
321     Handle<Context> declaration_context(context_arg->declaration_context());
322     DCHECK(declaration_context->has_extension());
323     holder = handle(declaration_context->extension(), isolate);
324     CHECK(holder->IsJSObject());
325   } else {
326     // For JSContextExtensionObjects, the initializer can be run multiple times
327     // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
328     // first assignment should go through. For JSGlobalObjects, additionally any
329     // code can run in between that modifies the declared property.
330     DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
331
332     LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
333     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
334     if (!maybe.has_value) return isolate->heap()->exception();
335     PropertyAttributes old_attributes = maybe.value;
336
337     // Ignore if we can't reconfigure the value.
338     if ((old_attributes & DONT_DELETE) != 0) {
339       if ((old_attributes & READ_ONLY) != 0 ||
340           it.state() == LookupIterator::ACCESSOR) {
341         return *value;
342       }
343       attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
344     }
345   }
346
347   RETURN_FAILURE_ON_EXCEPTION(
348       isolate, JSObject::SetOwnPropertyIgnoreAttributes(
349                    Handle<JSObject>::cast(holder), name, value, attr));
350
351   return *value;
352 }
353
354
355 static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
356                                            Handle<JSFunction> callee,
357                                            Object** parameters,
358                                            int argument_count) {
359   CHECK(!IsSubclassConstructor(callee->shared()->kind()));
360   DCHECK(callee->is_simple_parameter_list());
361   Handle<JSObject> result =
362       isolate->factory()->NewArgumentsObject(callee, argument_count);
363
364   // Allocate the elements if needed.
365   int parameter_count = callee->shared()->internal_formal_parameter_count();
366   if (argument_count > 0) {
367     if (parameter_count > 0) {
368       int mapped_count = Min(argument_count, parameter_count);
369       Handle<FixedArray> parameter_map =
370           isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
371       parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
372
373       Handle<Map> map = Map::Copy(handle(result->map()), "NewSloppyArguments");
374       map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
375
376       result->set_map(*map);
377       result->set_elements(*parameter_map);
378
379       // Store the context and the arguments array at the beginning of the
380       // parameter map.
381       Handle<Context> context(isolate->context());
382       Handle<FixedArray> arguments =
383           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
384       parameter_map->set(0, *context);
385       parameter_map->set(1, *arguments);
386
387       // Loop over the actual parameters backwards.
388       int index = argument_count - 1;
389       while (index >= mapped_count) {
390         // These go directly in the arguments array and have no
391         // corresponding slot in the parameter map.
392         arguments->set(index, *(parameters - index - 1));
393         --index;
394       }
395
396       Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
397       while (index >= 0) {
398         // Detect duplicate names to the right in the parameter list.
399         Handle<String> name(scope_info->ParameterName(index));
400         int context_local_count = scope_info->ContextLocalCount();
401         bool duplicate = false;
402         for (int j = index + 1; j < parameter_count; ++j) {
403           if (scope_info->ParameterName(j) == *name) {
404             duplicate = true;
405             break;
406           }
407         }
408
409         if (duplicate) {
410           // This goes directly in the arguments array with a hole in the
411           // parameter map.
412           arguments->set(index, *(parameters - index - 1));
413           parameter_map->set_the_hole(index + 2);
414         } else {
415           // The context index goes in the parameter map with a hole in the
416           // arguments array.
417           int context_index = -1;
418           for (int j = 0; j < context_local_count; ++j) {
419             if (scope_info->ContextLocalName(j) == *name) {
420               context_index = j;
421               break;
422             }
423           }
424
425           DCHECK(context_index >= 0);
426           arguments->set_the_hole(index);
427           parameter_map->set(
428               index + 2,
429               Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
430         }
431
432         --index;
433       }
434     } else {
435       // If there is no aliasing, the arguments object elements are not
436       // special in any way.
437       Handle<FixedArray> elements =
438           isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
439       result->set_elements(*elements);
440       for (int i = 0; i < argument_count; ++i) {
441         elements->set(i, *(parameters - i - 1));
442       }
443     }
444   }
445   return result;
446 }
447
448
449 static Handle<JSObject> NewStrictArguments(Isolate* isolate,
450                                            Handle<JSFunction> callee,
451                                            Object** parameters,
452                                            int argument_count) {
453   Handle<JSObject> result =
454       isolate->factory()->NewArgumentsObject(callee, argument_count);
455
456   if (argument_count > 0) {
457     Handle<FixedArray> array =
458         isolate->factory()->NewUninitializedFixedArray(argument_count);
459     DisallowHeapAllocation no_gc;
460     WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
461     for (int i = 0; i < argument_count; i++) {
462       array->set(i, *--parameters, mode);
463     }
464     result->set_elements(*array);
465   }
466   return result;
467 }
468
469
470 RUNTIME_FUNCTION(Runtime_NewArguments) {
471   HandleScope scope(isolate);
472   DCHECK(args.length() == 1);
473   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
474   JavaScriptFrameIterator it(isolate);
475
476   // Find the frame that holds the actual arguments passed to the function.
477   it.AdvanceToArgumentsFrame();
478   JavaScriptFrame* frame = it.frame();
479
480   // Determine parameter location on the stack and dispatch on language mode.
481   int argument_count = frame->GetArgumentsLength();
482   Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
483
484   return (is_strict(callee->shared()->language_mode()) ||
485              !callee->is_simple_parameter_list())
486              ? *NewStrictArguments(isolate, callee, parameters, argument_count)
487              : *NewSloppyArguments(isolate, callee, parameters, argument_count);
488 }
489
490
491 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
492   HandleScope scope(isolate);
493   DCHECK(args.length() == 3);
494   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
495   Object** parameters = reinterpret_cast<Object**>(args[1]);
496   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
497   return *NewSloppyArguments(isolate, callee, parameters, argument_count);
498 }
499
500
501 RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
502   HandleScope scope(isolate);
503   DCHECK(args.length() == 3);
504   CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
505   Object** parameters = reinterpret_cast<Object**>(args[1]);
506   CONVERT_SMI_ARG_CHECKED(argument_count, 2);
507   return *NewStrictArguments(isolate, callee, parameters, argument_count);
508 }
509
510
511 static Handle<JSArray> NewRestParam(Isolate* isolate,
512                                     Object** parameters,
513                                     int num_params,
514                                     int rest_index) {
515   parameters -= rest_index;
516   int num_elements = std::max(0, num_params - rest_index);
517   Handle<FixedArray> elements =
518       isolate->factory()->NewUninitializedFixedArray(num_elements);
519   for (int i = 0; i < num_elements; ++i) {
520     elements->set(i, *--parameters);
521   }
522   return isolate->factory()->NewJSArrayWithElements(elements, FAST_ELEMENTS,
523                                                     num_elements);
524 }
525
526
527 RUNTIME_FUNCTION(Runtime_NewRestParam) {
528   HandleScope scope(isolate);
529   DCHECK(args.length() == 3);
530   Object** parameters = reinterpret_cast<Object**>(args[0]);
531   CONVERT_SMI_ARG_CHECKED(num_params, 1);
532   CONVERT_SMI_ARG_CHECKED(rest_index, 2);
533
534   return *NewRestParam(isolate, parameters, num_params, rest_index);
535 }
536
537
538 RUNTIME_FUNCTION(Runtime_NewRestParamSlow) {
539   HandleScope scope(isolate);
540   DCHECK(args.length() == 1);
541   CONVERT_SMI_ARG_CHECKED(rest_index, 0);
542
543   JavaScriptFrameIterator it(isolate);
544
545   // Find the frame that holds the actual arguments passed to the function.
546   it.AdvanceToArgumentsFrame();
547   JavaScriptFrame* frame = it.frame();
548
549   int argument_count = frame->GetArgumentsLength();
550   Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
551
552   return *NewRestParam(isolate, parameters, argument_count, rest_index);
553 }
554
555
556 RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
557   HandleScope scope(isolate);
558   DCHECK(args.length() == 1);
559   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
560   Handle<Context> context(isolate->context());
561   PretenureFlag pretenure_flag = NOT_TENURED;
562   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
563                                                                 pretenure_flag);
564 }
565
566
567 RUNTIME_FUNCTION(Runtime_NewClosure) {
568   HandleScope scope(isolate);
569   DCHECK(args.length() == 3);
570   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
571   CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
572   CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
573
574   // The caller ensures that we pretenure closures that are assigned
575   // directly to properties.
576   PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
577   return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
578                                                                 pretenure_flag);
579 }
580
581 static Object* FindNameClash(Handle<ScopeInfo> scope_info,
582                              Handle<GlobalObject> global_object,
583                              Handle<ScriptContextTable> script_context) {
584   Isolate* isolate = scope_info->GetIsolate();
585   for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
586     Handle<String> name(scope_info->ContextLocalName(var));
587     VariableMode mode = scope_info->ContextLocalMode(var);
588     ScriptContextTable::LookupResult lookup;
589     if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
590       if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
591         return ThrowRedeclarationError(isolate, name);
592       }
593     }
594
595     if (IsLexicalVariableMode(mode)) {
596       LookupIterator it(global_object, name,
597                         LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
598       Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
599       if (!maybe.has_value) return isolate->heap()->exception();
600       if ((maybe.value & DONT_DELETE) != 0) {
601         return ThrowRedeclarationError(isolate, name);
602       }
603
604       GlobalObject::InvalidatePropertyCell(global_object, name);
605     }
606   }
607   return isolate->heap()->undefined_value();
608 }
609
610
611 RUNTIME_FUNCTION(Runtime_NewScriptContext) {
612   HandleScope scope(isolate);
613   DCHECK(args.length() == 2);
614
615   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
616   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
617   Handle<GlobalObject> global_object(function->context()->global_object());
618   Handle<Context> native_context(global_object->native_context());
619   Handle<ScriptContextTable> script_context_table(
620       native_context->script_context_table());
621
622   Handle<String> clashed_name;
623   Object* name_clash_result =
624       FindNameClash(scope_info, global_object, script_context_table);
625   if (isolate->has_pending_exception()) return name_clash_result;
626
627   Handle<Context> result =
628       isolate->factory()->NewScriptContext(function, scope_info);
629
630   DCHECK(function->context() == isolate->context());
631   DCHECK(function->context()->global_object() == result->global_object());
632
633   Handle<ScriptContextTable> new_script_context_table =
634       ScriptContextTable::Extend(script_context_table, result);
635   native_context->set_script_context_table(*new_script_context_table);
636   return *result;
637 }
638
639
640 RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
641   HandleScope scope(isolate);
642   DCHECK(args.length() == 1);
643
644   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
645
646   DCHECK(function->context() == isolate->context());
647   int length = function->shared()->scope_info()->ContextLength();
648   return *isolate->factory()->NewFunctionContext(length, function);
649 }
650
651
652 RUNTIME_FUNCTION(Runtime_PushWithContext) {
653   HandleScope scope(isolate);
654   DCHECK(args.length() == 2);
655   Handle<JSReceiver> extension_object;
656   if (args[0]->IsJSReceiver()) {
657     extension_object = args.at<JSReceiver>(0);
658   } else {
659     // Try to convert the object to a proper JavaScript object.
660     MaybeHandle<JSReceiver> maybe_object =
661         Object::ToObject(isolate, args.at<Object>(0));
662     if (!maybe_object.ToHandle(&extension_object)) {
663       Handle<Object> handle = args.at<Object>(0);
664       THROW_NEW_ERROR_RETURN_FAILURE(
665           isolate, NewTypeError("with_expression", HandleVector(&handle, 1)));
666     }
667   }
668
669   Handle<JSFunction> function;
670   if (args[1]->IsSmi()) {
671     // A smi sentinel indicates a context nested inside global code rather
672     // than some function.  There is a canonical empty function that can be
673     // gotten from the native context.
674     function = handle(isolate->native_context()->closure());
675   } else {
676     function = args.at<JSFunction>(1);
677   }
678
679   Handle<Context> current(isolate->context());
680   Handle<Context> context =
681       isolate->factory()->NewWithContext(function, current, extension_object);
682   isolate->set_context(*context);
683   return *context;
684 }
685
686
687 RUNTIME_FUNCTION(Runtime_PushCatchContext) {
688   HandleScope scope(isolate);
689   DCHECK(args.length() == 3);
690   CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
691   CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
692   Handle<JSFunction> function;
693   if (args[2]->IsSmi()) {
694     // A smi sentinel indicates a context nested inside global code rather
695     // than some function.  There is a canonical empty function that can be
696     // gotten from the native context.
697     function = handle(isolate->native_context()->closure());
698   } else {
699     function = args.at<JSFunction>(2);
700   }
701   Handle<Context> current(isolate->context());
702   Handle<Context> context = isolate->factory()->NewCatchContext(
703       function, current, name, thrown_object);
704   isolate->set_context(*context);
705   return *context;
706 }
707
708
709 RUNTIME_FUNCTION(Runtime_PushBlockContext) {
710   HandleScope scope(isolate);
711   DCHECK(args.length() == 2);
712   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
713   Handle<JSFunction> function;
714   if (args[1]->IsSmi()) {
715     // A smi sentinel indicates a context nested inside global code rather
716     // than some function.  There is a canonical empty function that can be
717     // gotten from the native context.
718     function = handle(isolate->native_context()->closure());
719   } else {
720     function = args.at<JSFunction>(1);
721   }
722   Handle<Context> current(isolate->context());
723   Handle<Context> context =
724       isolate->factory()->NewBlockContext(function, current, scope_info);
725   isolate->set_context(*context);
726   return *context;
727 }
728
729
730 RUNTIME_FUNCTION(Runtime_IsJSModule) {
731   SealHandleScope shs(isolate);
732   DCHECK(args.length() == 1);
733   CONVERT_ARG_CHECKED(Object, obj, 0);
734   return isolate->heap()->ToBoolean(obj->IsJSModule());
735 }
736
737
738 RUNTIME_FUNCTION(Runtime_PushModuleContext) {
739   SealHandleScope shs(isolate);
740   DCHECK(args.length() == 2);
741   CONVERT_SMI_ARG_CHECKED(index, 0);
742
743   if (!args[1]->IsScopeInfo()) {
744     // Module already initialized. Find hosting context and retrieve context.
745     Context* host = Context::cast(isolate->context())->script_context();
746     Context* context = Context::cast(host->get(index));
747     DCHECK(context->previous() == isolate->context());
748     isolate->set_context(context);
749     return context;
750   }
751
752   CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
753
754   // Allocate module context.
755   HandleScope scope(isolate);
756   Factory* factory = isolate->factory();
757   Handle<Context> context = factory->NewModuleContext(scope_info);
758   Handle<JSModule> module = factory->NewJSModule(context, scope_info);
759   context->set_module(*module);
760   Context* previous = isolate->context();
761   context->set_previous(previous);
762   context->set_closure(previous->closure());
763   context->set_global_object(previous->global_object());
764   isolate->set_context(*context);
765
766   // Find hosting scope and initialize internal variable holding module there.
767   previous->script_context()->set(index, *context);
768
769   return *context;
770 }
771
772
773 RUNTIME_FUNCTION(Runtime_DeclareModules) {
774   HandleScope scope(isolate);
775   DCHECK(args.length() == 1);
776   CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
777   Context* host_context = isolate->context();
778
779   for (int i = 0; i < descriptions->length(); ++i) {
780     Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
781     int host_index = description->host_index();
782     Handle<Context> context(Context::cast(host_context->get(host_index)));
783     Handle<JSModule> module(context->module());
784
785     for (int j = 0; j < description->length(); ++j) {
786       Handle<String> name(description->name(j));
787       VariableMode mode = description->mode(j);
788       int index = description->index(j);
789       switch (mode) {
790         case VAR:
791         case LET:
792         case CONST:
793         case CONST_LEGACY: {
794           PropertyAttributes attr =
795               IsImmutableVariableMode(mode) ? FROZEN : SEALED;
796           Handle<AccessorInfo> info =
797               Accessors::MakeModuleExport(name, index, attr);
798           Handle<Object> result =
799               JSObject::SetAccessor(module, info).ToHandleChecked();
800           DCHECK(!result->IsUndefined());
801           USE(result);
802           break;
803         }
804         case INTERNAL:
805         case TEMPORARY:
806         case DYNAMIC:
807         case DYNAMIC_GLOBAL:
808         case DYNAMIC_LOCAL:
809           UNREACHABLE();
810       }
811     }
812
813     JSObject::PreventExtensions(module).Assert();
814   }
815
816   DCHECK(!isolate->has_pending_exception());
817   return isolate->heap()->undefined_value();
818 }
819
820
821 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
822   HandleScope scope(isolate);
823   DCHECK(args.length() == 2);
824
825   CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
826   CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
827
828   int index;
829   PropertyAttributes attributes;
830   ContextLookupFlags flags = FOLLOW_CHAINS;
831   BindingFlags binding_flags;
832   Handle<Object> holder =
833       context->Lookup(name, flags, &index, &attributes, &binding_flags);
834
835   // If the slot was not found the result is true.
836   if (holder.is_null()) {
837     return isolate->heap()->true_value();
838   }
839
840   // If the slot was found in a context, it should be DONT_DELETE.
841   if (holder->IsContext()) {
842     return isolate->heap()->false_value();
843   }
844
845   // The slot was found in a JSObject, either a context extension object,
846   // the global object, or the subject of a with.  Try to delete it
847   // (respecting DONT_DELETE).
848   Handle<JSObject> object = Handle<JSObject>::cast(holder);
849   Handle<Object> result;
850   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
851                                      JSReceiver::DeleteProperty(object, name));
852   return *result;
853 }
854
855
856 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) {
857   DCHECK(!holder->IsGlobalObject());
858   Context* top = isolate->context();
859   // Get the context extension function.
860   JSFunction* context_extension_function =
861       top->native_context()->context_extension_function();
862   // If the holder isn't a context extension object, we just return it
863   // as the receiver. This allows arguments objects to be used as
864   // receivers, but only if they are put in the context scope chain
865   // explicitly via a with-statement.
866   Object* constructor = holder->map()->constructor();
867   if (constructor != context_extension_function) return holder;
868   // Fall back to using the global object as the implicit receiver if
869   // the property turns out to be a local variable allocated in a
870   // context extension object - introduced via eval.
871   return isolate->heap()->undefined_value();
872 }
873
874
875 static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate,
876                                        bool throw_error) {
877   HandleScope scope(isolate);
878   DCHECK_EQ(2, args.length());
879
880   if (!args[0]->IsContext() || !args[1]->IsString()) {
881     return MakePair(isolate->ThrowIllegalOperation(), NULL);
882   }
883   Handle<Context> context = args.at<Context>(0);
884   Handle<String> name = args.at<String>(1);
885
886   int index;
887   PropertyAttributes attributes;
888   ContextLookupFlags flags = FOLLOW_CHAINS;
889   BindingFlags binding_flags;
890   Handle<Object> holder =
891       context->Lookup(name, flags, &index, &attributes, &binding_flags);
892   if (isolate->has_pending_exception()) {
893     return MakePair(isolate->heap()->exception(), NULL);
894   }
895
896   // If the index is non-negative, the slot has been found in a context.
897   if (index >= 0) {
898     DCHECK(holder->IsContext());
899     // If the "property" we were looking for is a local variable, the
900     // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
901     Handle<Object> receiver = isolate->factory()->undefined_value();
902     Object* value = Context::cast(*holder)->get(index);
903     // Check for uninitialized bindings.
904     switch (binding_flags) {
905       case MUTABLE_CHECK_INITIALIZED:
906       case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
907         if (value->IsTheHole()) {
908           Handle<Object> error;
909           MaybeHandle<Object> maybe_error =
910               isolate->factory()->NewReferenceError("not_defined",
911                                                     HandleVector(&name, 1));
912           if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
913           return MakePair(isolate->heap()->exception(), NULL);
914         }
915       // FALLTHROUGH
916       case MUTABLE_IS_INITIALIZED:
917       case IMMUTABLE_IS_INITIALIZED:
918       case IMMUTABLE_IS_INITIALIZED_HARMONY:
919         DCHECK(!value->IsTheHole());
920         return MakePair(value, *receiver);
921       case IMMUTABLE_CHECK_INITIALIZED:
922         if (value->IsTheHole()) {
923           DCHECK((attributes & READ_ONLY) != 0);
924           value = isolate->heap()->undefined_value();
925         }
926         return MakePair(value, *receiver);
927       case MISSING_BINDING:
928         UNREACHABLE();
929         return MakePair(NULL, NULL);
930     }
931   }
932
933   // Otherwise, if the slot was found the holder is a context extension
934   // object, subject of a with, or a global object.  We read the named
935   // property from it.
936   if (!holder.is_null()) {
937     Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
938 #ifdef DEBUG
939     if (!object->IsJSProxy()) {
940       Maybe<bool> maybe = JSReceiver::HasProperty(object, name);
941       DCHECK(maybe.has_value);
942       DCHECK(maybe.value);
943     }
944 #endif
945     // GetProperty below can cause GC.
946     Handle<Object> receiver_handle(
947         object->IsGlobalObject()
948             ? Object::cast(isolate->heap()->undefined_value())
949             : object->IsJSProxy() ? static_cast<Object*>(*object)
950                                   : ComputeReceiverForNonGlobal(
951                                         isolate, JSObject::cast(*object)),
952         isolate);
953
954     // No need to unhole the value here.  This is taken care of by the
955     // GetProperty function.
956     Handle<Object> value;
957     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
958         isolate, value, Object::GetProperty(object, name),
959         MakePair(isolate->heap()->exception(), NULL));
960     return MakePair(*value, *receiver_handle);
961   }
962
963   if (throw_error) {
964     // The property doesn't exist - throw exception.
965     Handle<Object> error;
966     MaybeHandle<Object> maybe_error = isolate->factory()->NewReferenceError(
967         "not_defined", HandleVector(&name, 1));
968     if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
969     return MakePair(isolate->heap()->exception(), NULL);
970   } else {
971     // The property doesn't exist - return undefined.
972     return MakePair(isolate->heap()->undefined_value(),
973                     isolate->heap()->undefined_value());
974   }
975 }
976
977
978 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) {
979   return LoadLookupSlotHelper(args, isolate, true);
980 }
981
982
983 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) {
984   return LoadLookupSlotHelper(args, isolate, false);
985 }
986
987
988 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
989   HandleScope scope(isolate);
990   DCHECK(args.length() == 4);
991
992   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
993   CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
994   CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
995   CONVERT_LANGUAGE_MODE_ARG_CHECKED(language_mode, 3);
996
997   int index;
998   PropertyAttributes attributes;
999   ContextLookupFlags flags = FOLLOW_CHAINS;
1000   BindingFlags binding_flags;
1001   Handle<Object> holder =
1002       context->Lookup(name, flags, &index, &attributes, &binding_flags);
1003   // In case of JSProxy, an exception might have been thrown.
1004   if (isolate->has_pending_exception()) return isolate->heap()->exception();
1005
1006   // The property was found in a context slot.
1007   if (index >= 0) {
1008     if ((attributes & READ_ONLY) == 0) {
1009       Handle<Context>::cast(holder)->set(index, *value);
1010     } else if (is_strict(language_mode)) {
1011       // Setting read only property in strict mode.
1012       THROW_NEW_ERROR_RETURN_FAILURE(
1013           isolate,
1014           NewTypeError("strict_cannot_assign", HandleVector(&name, 1)));
1015     }
1016     return *value;
1017   }
1018
1019   // Slow case: The property is not in a context slot.  It is either in a
1020   // context extension object, a property of the subject of a with, or a
1021   // property of the global object.
1022   Handle<JSReceiver> object;
1023   if (attributes != ABSENT) {
1024     // The property exists on the holder.
1025     object = Handle<JSReceiver>::cast(holder);
1026   } else if (is_strict(language_mode)) {
1027     // If absent in strict mode: throw.
1028     THROW_NEW_ERROR_RETURN_FAILURE(
1029         isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
1030   } else {
1031     // If absent in sloppy mode: add the property to the global object.
1032     object = Handle<JSReceiver>(context->global_object());
1033   }
1034
1035   RETURN_FAILURE_ON_EXCEPTION(
1036       isolate, Object::SetProperty(object, name, value, language_mode));
1037
1038   return *value;
1039 }
1040
1041
1042 RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
1043   SealHandleScope shs(isolate);
1044   DCHECK(args.length() == 1);
1045   CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
1046
1047   // Compute the frame holding the arguments.
1048   JavaScriptFrameIterator it(isolate);
1049   it.AdvanceToArgumentsFrame();
1050   JavaScriptFrame* frame = it.frame();
1051
1052   // Get the actual number of provided arguments.
1053   const uint32_t n = frame->ComputeParametersCount();
1054
1055   // Try to convert the key to an index. If successful and within
1056   // index return the the argument from the frame.
1057   uint32_t index;
1058   if (raw_key->ToArrayIndex(&index) && index < n) {
1059     return frame->GetParameter(index);
1060   }
1061
1062   HandleScope scope(isolate);
1063   if (raw_key->IsSymbol()) {
1064     Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
1065     if (Name::Equals(symbol, isolate->factory()->iterator_symbol())) {
1066       return isolate->native_context()->array_values_iterator();
1067     }
1068     // Lookup in the initial Object.prototype object.
1069     Handle<Object> result;
1070     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1071         isolate, result,
1072         Object::GetProperty(isolate->initial_object_prototype(),
1073                             Handle<Symbol>::cast(raw_key)));
1074     return *result;
1075   }
1076
1077   // Convert the key to a string.
1078   Handle<Object> converted;
1079   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, converted,
1080                                      Execution::ToString(isolate, raw_key));
1081   Handle<String> key = Handle<String>::cast(converted);
1082
1083   // Try to convert the string key into an array index.
1084   if (key->AsArrayIndex(&index)) {
1085     if (index < n) {
1086       return frame->GetParameter(index);
1087     } else {
1088       Handle<Object> initial_prototype(isolate->initial_object_prototype());
1089       Handle<Object> result;
1090       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1091           isolate, result,
1092           Object::GetElement(isolate, initial_prototype, index));
1093       return *result;
1094     }
1095   }
1096
1097   // Handle special arguments properties.
1098   if (String::Equals(isolate->factory()->length_string(), key)) {
1099     return Smi::FromInt(n);
1100   }
1101   if (String::Equals(isolate->factory()->callee_string(), key)) {
1102     JSFunction* function = frame->function();
1103     if (is_strict(function->shared()->language_mode())) {
1104       THROW_NEW_ERROR_RETURN_FAILURE(
1105           isolate, NewTypeError("strict_arguments_callee",
1106                                 HandleVector<Object>(NULL, 0)));
1107     }
1108     return function;
1109   }
1110
1111   // Lookup in the initial Object.prototype object.
1112   Handle<Object> result;
1113   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1114       isolate, result,
1115       Object::GetProperty(isolate->initial_object_prototype(), key));
1116   return *result;
1117 }
1118
1119
1120 RUNTIME_FUNCTION(RuntimeReference_ArgumentsLength) {
1121   SealHandleScope shs(isolate);
1122   DCHECK(args.length() == 0);
1123   JavaScriptFrameIterator it(isolate);
1124   JavaScriptFrame* frame = it.frame();
1125   return Smi::FromInt(frame->GetArgumentsLength());
1126 }
1127
1128
1129 RUNTIME_FUNCTION(RuntimeReference_Arguments) {
1130   SealHandleScope shs(isolate);
1131   return __RT_impl_Runtime_GetArgumentsProperty(args, isolate);
1132 }
1133 }
1134 }  // namespace v8::internal