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