Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1916)

Side by Side Diff: src/runtime/runtime-scopes.cc

Issue 612383002: Split yet more runtime functions into separate files. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime/runtime-regexp.cc ('k') | src/runtime/runtime-symbol.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/accessors.h"
8 #include "src/arguments.h"
9 #include "src/frames-inl.h"
10 #include "src/runtime/runtime.h"
11 #include "src/runtime/runtime-utils.h"
12 #include "src/scopeinfo.h"
13 #include "src/scopes.h"
14
15 namespace v8 {
16 namespace internal {
17
18 static Object* ThrowRedeclarationError(Isolate* isolate, Handle<String> name) {
19 HandleScope scope(isolate);
20 Handle<Object> args[1] = {name};
21 THROW_NEW_ERROR_RETURN_FAILURE(
22 isolate, NewTypeError("var_redeclaration", HandleVector(args, 1)));
23 }
24
25
26 // May throw a RedeclarationError.
27 static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global,
28 Handle<String> name, Handle<Object> value,
29 PropertyAttributes attr, bool is_var,
30 bool is_const, bool is_function) {
31 // Do the lookup own properties only, see ES5 erratum.
32 LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
33 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
34 if (!maybe.has_value) return isolate->heap()->exception();
35
36 if (it.IsFound()) {
37 PropertyAttributes old_attributes = maybe.value;
38 // The name was declared before; check for conflicting re-declarations.
39 if (is_const) return ThrowRedeclarationError(isolate, name);
40
41 // Skip var re-declarations.
42 if (is_var) return isolate->heap()->undefined_value();
43
44 DCHECK(is_function);
45 if ((old_attributes & DONT_DELETE) != 0) {
46 // Only allow reconfiguring globals to functions in user code (no
47 // natives, which are marked as read-only).
48 DCHECK((attr & READ_ONLY) == 0);
49
50 // Check whether we can reconfigure the existing property into a
51 // function.
52 PropertyDetails old_details = it.property_details();
53 // TODO(verwaest): CALLBACKS invalidly includes ExecutableAccessInfo,
54 // which are actually data properties, not accessor properties.
55 if (old_details.IsReadOnly() || old_details.IsDontEnum() ||
56 old_details.type() == CALLBACKS) {
57 return ThrowRedeclarationError(isolate, name);
58 }
59 // If the existing property is not configurable, keep its attributes. Do
60 attr = old_attributes;
61 }
62 }
63
64 // Define or redefine own property.
65 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
66 global, name, value, attr));
67
68 return isolate->heap()->undefined_value();
69 }
70
71
72 RUNTIME_FUNCTION(Runtime_DeclareGlobals) {
73 HandleScope scope(isolate);
74 DCHECK(args.length() == 3);
75 Handle<GlobalObject> global(isolate->global_object());
76
77 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
78 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
79 CONVERT_SMI_ARG_CHECKED(flags, 2);
80
81 // Traverse the name/value pairs and set the properties.
82 int length = pairs->length();
83 for (int i = 0; i < length; i += 2) {
84 HandleScope scope(isolate);
85 Handle<String> name(String::cast(pairs->get(i)));
86 Handle<Object> initial_value(pairs->get(i + 1), isolate);
87
88 // We have to declare a global const property. To capture we only
89 // assign to it when evaluating the assignment for "const x =
90 // <expr>" the initial value is the hole.
91 bool is_var = initial_value->IsUndefined();
92 bool is_const = initial_value->IsTheHole();
93 bool is_function = initial_value->IsSharedFunctionInfo();
94 DCHECK(is_var + is_const + is_function == 1);
95
96 Handle<Object> value;
97 if (is_function) {
98 // Copy the function and update its context. Use it as value.
99 Handle<SharedFunctionInfo> shared =
100 Handle<SharedFunctionInfo>::cast(initial_value);
101 Handle<JSFunction> function =
102 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
103 TENURED);
104 value = function;
105 } else {
106 value = isolate->factory()->undefined_value();
107 }
108
109 // Compute the property attributes. According to ECMA-262,
110 // the property must be non-configurable except in eval.
111 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
112 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
113 int attr = NONE;
114 if (is_const) attr |= READ_ONLY;
115 if (is_function && is_native) attr |= READ_ONLY;
116 if (!is_const && !is_eval) attr |= DONT_DELETE;
117
118 Object* result = DeclareGlobals(isolate, global, name, value,
119 static_cast<PropertyAttributes>(attr),
120 is_var, is_const, is_function);
121 if (isolate->has_pending_exception()) return result;
122 }
123
124 return isolate->heap()->undefined_value();
125 }
126
127
128 RUNTIME_FUNCTION(Runtime_InitializeVarGlobal) {
129 HandleScope scope(isolate);
130 // args[0] == name
131 // args[1] == language_mode
132 // args[2] == value (optional)
133
134 // Determine if we need to assign to the variable if it already
135 // exists (based on the number of arguments).
136 RUNTIME_ASSERT(args.length() == 3);
137
138 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
139 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
140 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
141
142 Handle<GlobalObject> global(isolate->context()->global_object());
143 Handle<Object> result;
144 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
145 isolate, result, Object::SetProperty(global, name, value, strict_mode));
146 return *result;
147 }
148
149
150 RUNTIME_FUNCTION(Runtime_InitializeConstGlobal) {
151 HandleScope handle_scope(isolate);
152 // All constants are declared with an initial value. The name
153 // of the constant is the first argument and the initial value
154 // is the second.
155 RUNTIME_ASSERT(args.length() == 2);
156 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
157 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
158
159 Handle<GlobalObject> global = isolate->global_object();
160
161 // Lookup the property as own on the global object.
162 LookupIterator it(global, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
163 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
164 DCHECK(maybe.has_value);
165 PropertyAttributes old_attributes = maybe.value;
166
167 PropertyAttributes attr =
168 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
169 // Set the value if the property is either missing, or the property attributes
170 // allow setting the value without invoking an accessor.
171 if (it.IsFound()) {
172 // Ignore if we can't reconfigure the value.
173 if ((old_attributes & DONT_DELETE) != 0) {
174 if ((old_attributes & READ_ONLY) != 0 ||
175 it.state() == LookupIterator::ACCESSOR) {
176 return *value;
177 }
178 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
179 }
180 }
181
182 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
183 global, name, value, attr));
184
185 return *value;
186 }
187
188
189 RUNTIME_FUNCTION(Runtime_DeclareLookupSlot) {
190 HandleScope scope(isolate);
191 DCHECK(args.length() == 4);
192
193 // Declarations are always made in a function, native, or global context. In
194 // the case of eval code, the context passed is the context of the caller,
195 // which may be some nested context and not the declaration context.
196 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 0);
197 Handle<Context> context(context_arg->declaration_context());
198 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
199 CONVERT_SMI_ARG_CHECKED(attr_arg, 2);
200 PropertyAttributes attr = static_cast<PropertyAttributes>(attr_arg);
201 RUNTIME_ASSERT(attr == READ_ONLY || attr == NONE);
202 CONVERT_ARG_HANDLE_CHECKED(Object, initial_value, 3);
203
204 // TODO(verwaest): Unify the encoding indicating "var" with DeclareGlobals.
205 bool is_var = *initial_value == NULL;
206 bool is_const = initial_value->IsTheHole();
207 bool is_function = initial_value->IsJSFunction();
208 DCHECK(is_var + is_const + is_function == 1);
209
210 int index;
211 PropertyAttributes attributes;
212 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
213 BindingFlags binding_flags;
214 Handle<Object> holder =
215 context->Lookup(name, flags, &index, &attributes, &binding_flags);
216
217 Handle<JSObject> object;
218 Handle<Object> value =
219 is_function ? initial_value
220 : Handle<Object>::cast(isolate->factory()->undefined_value());
221
222 // TODO(verwaest): This case should probably not be covered by this function,
223 // but by DeclareGlobals instead.
224 if ((attributes != ABSENT && holder->IsJSGlobalObject()) ||
225 (context_arg->has_extension() &&
226 context_arg->extension()->IsJSGlobalObject())) {
227 return DeclareGlobals(isolate, Handle<JSGlobalObject>::cast(holder), name,
228 value, attr, is_var, is_const, is_function);
229 }
230
231 if (attributes != ABSENT) {
232 // The name was declared before; check for conflicting re-declarations.
233 if (is_const || (attributes & READ_ONLY) != 0) {
234 return ThrowRedeclarationError(isolate, name);
235 }
236
237 // Skip var re-declarations.
238 if (is_var) return isolate->heap()->undefined_value();
239
240 DCHECK(is_function);
241 if (index >= 0) {
242 DCHECK(holder.is_identical_to(context));
243 context->set(index, *initial_value);
244 return isolate->heap()->undefined_value();
245 }
246
247 object = Handle<JSObject>::cast(holder);
248
249 } else if (context->has_extension()) {
250 object = handle(JSObject::cast(context->extension()));
251 DCHECK(object->IsJSContextExtensionObject() || object->IsJSGlobalObject());
252 } else {
253 DCHECK(context->IsFunctionContext());
254 object =
255 isolate->factory()->NewJSObject(isolate->context_extension_function());
256 context->set_extension(*object);
257 }
258
259 RETURN_FAILURE_ON_EXCEPTION(isolate, JSObject::SetOwnPropertyIgnoreAttributes(
260 object, name, value, attr));
261
262 return isolate->heap()->undefined_value();
263 }
264
265
266 RUNTIME_FUNCTION(Runtime_InitializeLegacyConstLookupSlot) {
267 HandleScope scope(isolate);
268 DCHECK(args.length() == 3);
269
270 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
271 DCHECK(!value->IsTheHole());
272 // Initializations are always done in a function or native context.
273 CONVERT_ARG_HANDLE_CHECKED(Context, context_arg, 1);
274 Handle<Context> context(context_arg->declaration_context());
275 CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
276
277 int index;
278 PropertyAttributes attributes;
279 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
280 BindingFlags binding_flags;
281 Handle<Object> holder =
282 context->Lookup(name, flags, &index, &attributes, &binding_flags);
283
284 if (index >= 0) {
285 DCHECK(holder->IsContext());
286 // Property was found in a context. Perform the assignment if the constant
287 // was uninitialized.
288 Handle<Context> context = Handle<Context>::cast(holder);
289 DCHECK((attributes & READ_ONLY) != 0);
290 if (context->get(index)->IsTheHole()) context->set(index, *value);
291 return *value;
292 }
293
294 PropertyAttributes attr =
295 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
296
297 // Strict mode handling not needed (legacy const is disallowed in strict
298 // mode).
299
300 // The declared const was configurable, and may have been deleted in the
301 // meanwhile. If so, re-introduce the variable in the context extension.
302 DCHECK(context_arg->has_extension());
303 if (attributes == ABSENT) {
304 holder = handle(context_arg->extension(), isolate);
305 } else {
306 // For JSContextExtensionObjects, the initializer can be run multiple times
307 // if in a for loop: for (var i = 0; i < 2; i++) { const x = i; }. Only the
308 // first assignment should go through. For JSGlobalObjects, additionally any
309 // code can run in between that modifies the declared property.
310 DCHECK(holder->IsJSGlobalObject() || holder->IsJSContextExtensionObject());
311
312 LookupIterator it(holder, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
313 Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
314 if (!maybe.has_value) return isolate->heap()->exception();
315 PropertyAttributes old_attributes = maybe.value;
316
317 // Ignore if we can't reconfigure the value.
318 if ((old_attributes & DONT_DELETE) != 0) {
319 if ((old_attributes & READ_ONLY) != 0 ||
320 it.state() == LookupIterator::ACCESSOR) {
321 return *value;
322 }
323 attr = static_cast<PropertyAttributes>(old_attributes | READ_ONLY);
324 }
325 }
326
327 RETURN_FAILURE_ON_EXCEPTION(
328 isolate, JSObject::SetOwnPropertyIgnoreAttributes(
329 Handle<JSObject>::cast(holder), name, value, attr));
330
331 return *value;
332 }
333
334
335 static Handle<JSObject> NewSloppyArguments(Isolate* isolate,
336 Handle<JSFunction> callee,
337 Object** parameters,
338 int argument_count) {
339 Handle<JSObject> result =
340 isolate->factory()->NewArgumentsObject(callee, argument_count);
341
342 // Allocate the elements if needed.
343 int parameter_count = callee->shared()->formal_parameter_count();
344 if (argument_count > 0) {
345 if (parameter_count > 0) {
346 int mapped_count = Min(argument_count, parameter_count);
347 Handle<FixedArray> parameter_map =
348 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
349 parameter_map->set_map(isolate->heap()->sloppy_arguments_elements_map());
350
351 Handle<Map> map = Map::Copy(handle(result->map()));
352 map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
353
354 result->set_map(*map);
355 result->set_elements(*parameter_map);
356
357 // Store the context and the arguments array at the beginning of the
358 // parameter map.
359 Handle<Context> context(isolate->context());
360 Handle<FixedArray> arguments =
361 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
362 parameter_map->set(0, *context);
363 parameter_map->set(1, *arguments);
364
365 // Loop over the actual parameters backwards.
366 int index = argument_count - 1;
367 while (index >= mapped_count) {
368 // These go directly in the arguments array and have no
369 // corresponding slot in the parameter map.
370 arguments->set(index, *(parameters - index - 1));
371 --index;
372 }
373
374 Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
375 while (index >= 0) {
376 // Detect duplicate names to the right in the parameter list.
377 Handle<String> name(scope_info->ParameterName(index));
378 int context_local_count = scope_info->ContextLocalCount();
379 bool duplicate = false;
380 for (int j = index + 1; j < parameter_count; ++j) {
381 if (scope_info->ParameterName(j) == *name) {
382 duplicate = true;
383 break;
384 }
385 }
386
387 if (duplicate) {
388 // This goes directly in the arguments array with a hole in the
389 // parameter map.
390 arguments->set(index, *(parameters - index - 1));
391 parameter_map->set_the_hole(index + 2);
392 } else {
393 // The context index goes in the parameter map with a hole in the
394 // arguments array.
395 int context_index = -1;
396 for (int j = 0; j < context_local_count; ++j) {
397 if (scope_info->ContextLocalName(j) == *name) {
398 context_index = j;
399 break;
400 }
401 }
402 DCHECK(context_index >= 0);
403 arguments->set_the_hole(index);
404 parameter_map->set(
405 index + 2,
406 Smi::FromInt(Context::MIN_CONTEXT_SLOTS + context_index));
407 }
408
409 --index;
410 }
411 } else {
412 // If there is no aliasing, the arguments object elements are not
413 // special in any way.
414 Handle<FixedArray> elements =
415 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
416 result->set_elements(*elements);
417 for (int i = 0; i < argument_count; ++i) {
418 elements->set(i, *(parameters - i - 1));
419 }
420 }
421 }
422 return result;
423 }
424
425
426 static Handle<JSObject> NewStrictArguments(Isolate* isolate,
427 Handle<JSFunction> callee,
428 Object** parameters,
429 int argument_count) {
430 Handle<JSObject> result =
431 isolate->factory()->NewArgumentsObject(callee, argument_count);
432
433 if (argument_count > 0) {
434 Handle<FixedArray> array =
435 isolate->factory()->NewUninitializedFixedArray(argument_count);
436 DisallowHeapAllocation no_gc;
437 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
438 for (int i = 0; i < argument_count; i++) {
439 array->set(i, *--parameters, mode);
440 }
441 result->set_elements(*array);
442 }
443 return result;
444 }
445
446
447 RUNTIME_FUNCTION(Runtime_NewArguments) {
448 HandleScope scope(isolate);
449 DCHECK(args.length() == 1);
450 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
451 JavaScriptFrameIterator it(isolate);
452
453 // Find the frame that holds the actual arguments passed to the function.
454 it.AdvanceToArgumentsFrame();
455 JavaScriptFrame* frame = it.frame();
456
457 // Determine parameter location on the stack and dispatch on language mode.
458 int argument_count = frame->GetArgumentsLength();
459 Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
460 return callee->shared()->strict_mode() == STRICT
461 ? *NewStrictArguments(isolate, callee, parameters, argument_count)
462 : *NewSloppyArguments(isolate, callee, parameters, argument_count);
463 }
464
465
466 RUNTIME_FUNCTION(Runtime_NewSloppyArguments) {
467 HandleScope scope(isolate);
468 DCHECK(args.length() == 3);
469 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0);
470 Object** parameters = reinterpret_cast<Object**>(args[1]);
471 CONVERT_SMI_ARG_CHECKED(argument_count, 2);
472 return *NewSloppyArguments(isolate, callee, parameters, argument_count);
473 }
474
475
476 RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
477 HandleScope scope(isolate);
478 DCHECK(args.length() == 3);
479 CONVERT_ARG_HANDLE_CHECKED(JSFunction, callee, 0)
480 Object** parameters = reinterpret_cast<Object**>(args[1]);
481 CONVERT_SMI_ARG_CHECKED(argument_count, 2);
482 return *NewStrictArguments(isolate, callee, parameters, argument_count);
483 }
484
485
486 RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
487 HandleScope scope(isolate);
488 DCHECK(args.length() == 1);
489 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
490 Handle<Context> context(isolate->context());
491 PretenureFlag pretenure_flag = NOT_TENURED;
492 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
493 pretenure_flag);
494 }
495
496
497 RUNTIME_FUNCTION(Runtime_NewClosure) {
498 HandleScope scope(isolate);
499 DCHECK(args.length() == 3);
500 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
501 CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
502 CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
503
504 // The caller ensures that we pretenure closures that are assigned
505 // directly to properties.
506 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
507 return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
508 pretenure_flag);
509 }
510
511
512 RUNTIME_FUNCTION(Runtime_NewGlobalContext) {
513 HandleScope scope(isolate);
514 DCHECK(args.length() == 2);
515
516 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
517 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
518 Handle<Context> result =
519 isolate->factory()->NewGlobalContext(function, scope_info);
520
521 DCHECK(function->context() == isolate->context());
522 DCHECK(function->context()->global_object() == result->global_object());
523 result->global_object()->set_global_context(*result);
524 return *result;
525 }
526
527
528 RUNTIME_FUNCTION(Runtime_NewFunctionContext) {
529 HandleScope scope(isolate);
530 DCHECK(args.length() == 1);
531
532 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
533
534 DCHECK(function->context() == isolate->context());
535 int length = function->shared()->scope_info()->ContextLength();
536 return *isolate->factory()->NewFunctionContext(length, function);
537 }
538
539
540 RUNTIME_FUNCTION(Runtime_PushWithContext) {
541 HandleScope scope(isolate);
542 DCHECK(args.length() == 2);
543 Handle<JSReceiver> extension_object;
544 if (args[0]->IsJSReceiver()) {
545 extension_object = args.at<JSReceiver>(0);
546 } else {
547 // Try to convert the object to a proper JavaScript object.
548 MaybeHandle<JSReceiver> maybe_object =
549 Object::ToObject(isolate, args.at<Object>(0));
550 if (!maybe_object.ToHandle(&extension_object)) {
551 Handle<Object> handle = args.at<Object>(0);
552 THROW_NEW_ERROR_RETURN_FAILURE(
553 isolate, NewTypeError("with_expression", HandleVector(&handle, 1)));
554 }
555 }
556
557 Handle<JSFunction> function;
558 if (args[1]->IsSmi()) {
559 // A smi sentinel indicates a context nested inside global code rather
560 // than some function. There is a canonical empty function that can be
561 // gotten from the native context.
562 function = handle(isolate->native_context()->closure());
563 } else {
564 function = args.at<JSFunction>(1);
565 }
566
567 Handle<Context> current(isolate->context());
568 Handle<Context> context =
569 isolate->factory()->NewWithContext(function, current, extension_object);
570 isolate->set_context(*context);
571 return *context;
572 }
573
574
575 RUNTIME_FUNCTION(Runtime_PushCatchContext) {
576 HandleScope scope(isolate);
577 DCHECK(args.length() == 3);
578 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
579 CONVERT_ARG_HANDLE_CHECKED(Object, thrown_object, 1);
580 Handle<JSFunction> function;
581 if (args[2]->IsSmi()) {
582 // A smi sentinel indicates a context nested inside global code rather
583 // than some function. There is a canonical empty function that can be
584 // gotten from the native context.
585 function = handle(isolate->native_context()->closure());
586 } else {
587 function = args.at<JSFunction>(2);
588 }
589 Handle<Context> current(isolate->context());
590 Handle<Context> context = isolate->factory()->NewCatchContext(
591 function, current, name, thrown_object);
592 isolate->set_context(*context);
593 return *context;
594 }
595
596
597 RUNTIME_FUNCTION(Runtime_PushBlockContext) {
598 HandleScope scope(isolate);
599 DCHECK(args.length() == 2);
600 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 0);
601 Handle<JSFunction> function;
602 if (args[1]->IsSmi()) {
603 // A smi sentinel indicates a context nested inside global code rather
604 // than some function. There is a canonical empty function that can be
605 // gotten from the native context.
606 function = handle(isolate->native_context()->closure());
607 } else {
608 function = args.at<JSFunction>(1);
609 }
610 Handle<Context> current(isolate->context());
611 Handle<Context> context =
612 isolate->factory()->NewBlockContext(function, current, scope_info);
613 isolate->set_context(*context);
614 return *context;
615 }
616
617
618 RUNTIME_FUNCTION(Runtime_IsJSModule) {
619 SealHandleScope shs(isolate);
620 DCHECK(args.length() == 1);
621 CONVERT_ARG_CHECKED(Object, obj, 0);
622 return isolate->heap()->ToBoolean(obj->IsJSModule());
623 }
624
625
626 RUNTIME_FUNCTION(Runtime_PushModuleContext) {
627 SealHandleScope shs(isolate);
628 DCHECK(args.length() == 2);
629 CONVERT_SMI_ARG_CHECKED(index, 0);
630
631 if (!args[1]->IsScopeInfo()) {
632 // Module already initialized. Find hosting context and retrieve context.
633 Context* host = Context::cast(isolate->context())->global_context();
634 Context* context = Context::cast(host->get(index));
635 DCHECK(context->previous() == isolate->context());
636 isolate->set_context(context);
637 return context;
638 }
639
640 CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
641
642 // Allocate module context.
643 HandleScope scope(isolate);
644 Factory* factory = isolate->factory();
645 Handle<Context> context = factory->NewModuleContext(scope_info);
646 Handle<JSModule> module = factory->NewJSModule(context, scope_info);
647 context->set_module(*module);
648 Context* previous = isolate->context();
649 context->set_previous(previous);
650 context->set_closure(previous->closure());
651 context->set_global_object(previous->global_object());
652 isolate->set_context(*context);
653
654 // Find hosting scope and initialize internal variable holding module there.
655 previous->global_context()->set(index, *context);
656
657 return *context;
658 }
659
660
661 RUNTIME_FUNCTION(Runtime_DeclareModules) {
662 HandleScope scope(isolate);
663 DCHECK(args.length() == 1);
664 CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
665 Context* host_context = isolate->context();
666
667 for (int i = 0; i < descriptions->length(); ++i) {
668 Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
669 int host_index = description->host_index();
670 Handle<Context> context(Context::cast(host_context->get(host_index)));
671 Handle<JSModule> module(context->module());
672
673 for (int j = 0; j < description->length(); ++j) {
674 Handle<String> name(description->name(j));
675 VariableMode mode = description->mode(j);
676 int index = description->index(j);
677 switch (mode) {
678 case VAR:
679 case LET:
680 case CONST:
681 case CONST_LEGACY: {
682 PropertyAttributes attr =
683 IsImmutableVariableMode(mode) ? FROZEN : SEALED;
684 Handle<AccessorInfo> info =
685 Accessors::MakeModuleExport(name, index, attr);
686 Handle<Object> result =
687 JSObject::SetAccessor(module, info).ToHandleChecked();
688 DCHECK(!result->IsUndefined());
689 USE(result);
690 break;
691 }
692 case MODULE: {
693 Object* referenced_context = Context::cast(host_context)->get(index);
694 Handle<JSModule> value(Context::cast(referenced_context)->module());
695 JSObject::SetOwnPropertyIgnoreAttributes(module, name, value, FROZEN)
696 .Assert();
697 break;
698 }
699 case INTERNAL:
700 case TEMPORARY:
701 case DYNAMIC:
702 case DYNAMIC_GLOBAL:
703 case DYNAMIC_LOCAL:
704 UNREACHABLE();
705 }
706 }
707
708 JSObject::PreventExtensions(module).Assert();
709 }
710
711 DCHECK(!isolate->has_pending_exception());
712 return isolate->heap()->undefined_value();
713 }
714
715
716 RUNTIME_FUNCTION(Runtime_DeleteLookupSlot) {
717 HandleScope scope(isolate);
718 DCHECK(args.length() == 2);
719
720 CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
721 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
722
723 int index;
724 PropertyAttributes attributes;
725 ContextLookupFlags flags = FOLLOW_CHAINS;
726 BindingFlags binding_flags;
727 Handle<Object> holder =
728 context->Lookup(name, flags, &index, &attributes, &binding_flags);
729
730 // If the slot was not found the result is true.
731 if (holder.is_null()) {
732 return isolate->heap()->true_value();
733 }
734
735 // If the slot was found in a context, it should be DONT_DELETE.
736 if (holder->IsContext()) {
737 return isolate->heap()->false_value();
738 }
739
740 // The slot was found in a JSObject, either a context extension object,
741 // the global object, or the subject of a with. Try to delete it
742 // (respecting DONT_DELETE).
743 Handle<JSObject> object = Handle<JSObject>::cast(holder);
744 Handle<Object> result;
745 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
746 JSReceiver::DeleteProperty(object, name));
747 return *result;
748 }
749
750
751 static Object* ComputeReceiverForNonGlobal(Isolate* isolate, JSObject* holder) {
752 DCHECK(!holder->IsGlobalObject());
753 Context* top = isolate->context();
754 // Get the context extension function.
755 JSFunction* context_extension_function =
756 top->native_context()->context_extension_function();
757 // If the holder isn't a context extension object, we just return it
758 // as the receiver. This allows arguments objects to be used as
759 // receivers, but only if they are put in the context scope chain
760 // explicitly via a with-statement.
761 Object* constructor = holder->map()->constructor();
762 if (constructor != context_extension_function) return holder;
763 // Fall back to using the global object as the implicit receiver if
764 // the property turns out to be a local variable allocated in a
765 // context extension object - introduced via eval.
766 return isolate->heap()->undefined_value();
767 }
768
769
770 static ObjectPair LoadLookupSlotHelper(Arguments args, Isolate* isolate,
771 bool throw_error) {
772 HandleScope scope(isolate);
773 DCHECK_EQ(2, args.length());
774
775 if (!args[0]->IsContext() || !args[1]->IsString()) {
776 return MakePair(isolate->ThrowIllegalOperation(), NULL);
777 }
778 Handle<Context> context = args.at<Context>(0);
779 Handle<String> name = args.at<String>(1);
780
781 int index;
782 PropertyAttributes attributes;
783 ContextLookupFlags flags = FOLLOW_CHAINS;
784 BindingFlags binding_flags;
785 Handle<Object> holder =
786 context->Lookup(name, flags, &index, &attributes, &binding_flags);
787 if (isolate->has_pending_exception()) {
788 return MakePair(isolate->heap()->exception(), NULL);
789 }
790
791 // If the index is non-negative, the slot has been found in a context.
792 if (index >= 0) {
793 DCHECK(holder->IsContext());
794 // If the "property" we were looking for is a local variable, the
795 // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
796 Handle<Object> receiver = isolate->factory()->undefined_value();
797 Object* value = Context::cast(*holder)->get(index);
798 // Check for uninitialized bindings.
799 switch (binding_flags) {
800 case MUTABLE_CHECK_INITIALIZED:
801 case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
802 if (value->IsTheHole()) {
803 Handle<Object> error;
804 MaybeHandle<Object> maybe_error =
805 isolate->factory()->NewReferenceError("not_defined",
806 HandleVector(&name, 1));
807 if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
808 return MakePair(isolate->heap()->exception(), NULL);
809 }
810 // FALLTHROUGH
811 case MUTABLE_IS_INITIALIZED:
812 case IMMUTABLE_IS_INITIALIZED:
813 case IMMUTABLE_IS_INITIALIZED_HARMONY:
814 DCHECK(!value->IsTheHole());
815 return MakePair(value, *receiver);
816 case IMMUTABLE_CHECK_INITIALIZED:
817 if (value->IsTheHole()) {
818 DCHECK((attributes & READ_ONLY) != 0);
819 value = isolate->heap()->undefined_value();
820 }
821 return MakePair(value, *receiver);
822 case MISSING_BINDING:
823 UNREACHABLE();
824 return MakePair(NULL, NULL);
825 }
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 if (!holder.is_null()) {
832 Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
833 #ifdef DEBUG
834 if (!object->IsJSProxy()) {
835 Maybe<bool> maybe = JSReceiver::HasProperty(object, name);
836 DCHECK(maybe.has_value);
837 DCHECK(maybe.value);
838 }
839 #endif
840 // GetProperty below can cause GC.
841 Handle<Object> receiver_handle(
842 object->IsGlobalObject()
843 ? Object::cast(isolate->heap()->undefined_value())
844 : object->IsJSProxy() ? static_cast<Object*>(*object)
845 : ComputeReceiverForNonGlobal(
846 isolate, JSObject::cast(*object)),
847 isolate);
848
849 // No need to unhole the value here. This is taken care of by the
850 // GetProperty function.
851 Handle<Object> value;
852 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
853 isolate, value, Object::GetProperty(object, name),
854 MakePair(isolate->heap()->exception(), NULL));
855 return MakePair(*value, *receiver_handle);
856 }
857
858 if (throw_error) {
859 // The property doesn't exist - throw exception.
860 Handle<Object> error;
861 MaybeHandle<Object> maybe_error = isolate->factory()->NewReferenceError(
862 "not_defined", HandleVector(&name, 1));
863 if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
864 return MakePair(isolate->heap()->exception(), NULL);
865 } else {
866 // The property doesn't exist - return undefined.
867 return MakePair(isolate->heap()->undefined_value(),
868 isolate->heap()->undefined_value());
869 }
870 }
871
872
873 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlot) {
874 return LoadLookupSlotHelper(args, isolate, true);
875 }
876
877
878 RUNTIME_FUNCTION_RETURN_PAIR(Runtime_LoadLookupSlotNoReferenceError) {
879 return LoadLookupSlotHelper(args, isolate, false);
880 }
881
882
883 RUNTIME_FUNCTION(Runtime_StoreLookupSlot) {
884 HandleScope scope(isolate);
885 DCHECK(args.length() == 4);
886
887 CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
888 CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
889 CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
890 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
891
892 int index;
893 PropertyAttributes attributes;
894 ContextLookupFlags flags = FOLLOW_CHAINS;
895 BindingFlags binding_flags;
896 Handle<Object> holder =
897 context->Lookup(name, flags, &index, &attributes, &binding_flags);
898 // In case of JSProxy, an exception might have been thrown.
899 if (isolate->has_pending_exception()) return isolate->heap()->exception();
900
901 // The property was found in a context slot.
902 if (index >= 0) {
903 if ((attributes & READ_ONLY) == 0) {
904 Handle<Context>::cast(holder)->set(index, *value);
905 } else if (strict_mode == STRICT) {
906 // Setting read only property in strict mode.
907 THROW_NEW_ERROR_RETURN_FAILURE(
908 isolate,
909 NewTypeError("strict_cannot_assign", HandleVector(&name, 1)));
910 }
911 return *value;
912 }
913
914 // Slow case: The property is not in a context slot. It is either in a
915 // context extension object, a property of the subject of a with, or a
916 // property of the global object.
917 Handle<JSReceiver> object;
918 if (attributes != ABSENT) {
919 // The property exists on the holder.
920 object = Handle<JSReceiver>::cast(holder);
921 } else if (strict_mode == STRICT) {
922 // If absent in strict mode: throw.
923 THROW_NEW_ERROR_RETURN_FAILURE(
924 isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
925 } else {
926 // If absent in sloppy mode: add the property to the global object.
927 object = Handle<JSReceiver>(context->global_object());
928 }
929
930 RETURN_FAILURE_ON_EXCEPTION(
931 isolate, Object::SetProperty(object, name, value, strict_mode));
932
933 return *value;
934 }
935
936
937 RUNTIME_FUNCTION(Runtime_GetArgumentsProperty) {
938 SealHandleScope shs(isolate);
939 DCHECK(args.length() == 1);
940 CONVERT_ARG_HANDLE_CHECKED(Object, raw_key, 0);
941
942 // Compute the frame holding the arguments.
943 JavaScriptFrameIterator it(isolate);
944 it.AdvanceToArgumentsFrame();
945 JavaScriptFrame* frame = it.frame();
946
947 // Get the actual number of provided arguments.
948 const uint32_t n = frame->ComputeParametersCount();
949
950 // Try to convert the key to an index. If successful and within
951 // index return the the argument from the frame.
952 uint32_t index;
953 if (raw_key->ToArrayIndex(&index) && index < n) {
954 return frame->GetParameter(index);
955 }
956
957 HandleScope scope(isolate);
958 if (raw_key->IsSymbol()) {
959 Handle<Symbol> symbol = Handle<Symbol>::cast(raw_key);
960 if (symbol->Equals(isolate->native_context()->iterator_symbol())) {
961 return isolate->native_context()->array_values_iterator();
962 }
963 // Lookup in the initial Object.prototype object.
964 Handle<Object> result;
965 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
966 isolate, result,
967 Object::GetProperty(isolate->initial_object_prototype(),
968 Handle<Symbol>::cast(raw_key)));
969 return *result;
970 }
971
972 // Convert the key to a string.
973 Handle<Object> converted;
974 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, converted,
975 Execution::ToString(isolate, raw_key));
976 Handle<String> key = Handle<String>::cast(converted);
977
978 // Try to convert the string key into an array index.
979 if (key->AsArrayIndex(&index)) {
980 if (index < n) {
981 return frame->GetParameter(index);
982 } else {
983 Handle<Object> initial_prototype(isolate->initial_object_prototype());
984 Handle<Object> result;
985 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
986 isolate, result,
987 Object::GetElement(isolate, initial_prototype, index));
988 return *result;
989 }
990 }
991
992 // Handle special arguments properties.
993 if (String::Equals(isolate->factory()->length_string(), key)) {
994 return Smi::FromInt(n);
995 }
996 if (String::Equals(isolate->factory()->callee_string(), key)) {
997 JSFunction* function = frame->function();
998 if (function->shared()->strict_mode() == STRICT) {
999 THROW_NEW_ERROR_RETURN_FAILURE(
1000 isolate, NewTypeError("strict_arguments_callee",
1001 HandleVector<Object>(NULL, 0)));
1002 }
1003 return function;
1004 }
1005
1006 // Lookup in the initial Object.prototype object.
1007 Handle<Object> result;
1008 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1009 isolate, result,
1010 Object::GetProperty(isolate->initial_object_prototype(), key));
1011 return *result;
1012 }
1013
1014
1015 RUNTIME_FUNCTION(RuntimeReference_ArgumentsLength) {
1016 SealHandleScope shs(isolate);
1017 DCHECK(args.length() == 0);
1018 JavaScriptFrameIterator it(isolate);
1019 JavaScriptFrame* frame = it.frame();
1020 return Smi::FromInt(frame->GetArgumentsLength());
1021 }
1022
1023
1024 RUNTIME_FUNCTION(RuntimeReference_Arguments) {
1025 SealHandleScope shs(isolate);
1026 return __RT_impl_Runtime_GetArgumentsProperty(args, isolate);
1027 }
1028 }
1029 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime/runtime-regexp.cc ('k') | src/runtime/runtime-symbol.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698