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