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