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