OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
10 #include "src/deoptimizer.h" | 10 #include "src/deoptimizer.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 RUNTIME_ASSERT(f->RemovePrototype()); | 46 RUNTIME_ASSERT(f->RemovePrototype()); |
47 f->shared()->set_construct_stub( | 47 f->shared()->set_construct_stub( |
48 *isolate->builtins()->ConstructedNonConstructable()); | 48 *isolate->builtins()->ConstructedNonConstructable()); |
49 | 49 |
50 return isolate->heap()->undefined_value(); | 50 return isolate->heap()->undefined_value(); |
51 } | 51 } |
52 | 52 |
53 | 53 |
54 RUNTIME_FUNCTION(Runtime_FunctionGetScript) { | 54 RUNTIME_FUNCTION(Runtime_FunctionGetScript) { |
55 HandleScope scope(isolate); | 55 HandleScope scope(isolate); |
56 DCHECK(args.length() == 1); | 56 DCHECK_EQ(1, args.length()); |
| 57 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); |
57 | 58 |
58 CONVERT_ARG_CHECKED(JSFunction, fun, 0); | 59 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value(); |
59 Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate); | 60 Handle<Object> script(Handle<JSFunction>::cast(function)->shared()->script(), |
| 61 isolate); |
60 if (!script->IsScript()) return isolate->heap()->undefined_value(); | 62 if (!script->IsScript()) return isolate->heap()->undefined_value(); |
61 | |
62 return *Script::GetWrapper(Handle<Script>::cast(script)); | 63 return *Script::GetWrapper(Handle<Script>::cast(script)); |
63 } | 64 } |
64 | 65 |
65 | 66 |
66 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { | 67 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { |
67 HandleScope scope(isolate); | 68 HandleScope scope(isolate); |
68 DCHECK(args.length() == 1); | 69 DCHECK_EQ(1, args.length()); |
69 | 70 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); |
70 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0); | 71 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value(); |
71 Handle<SharedFunctionInfo> shared(f->shared()); | 72 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode(); |
72 return *shared->GetSourceCode(); | |
73 } | 73 } |
74 | 74 |
75 | 75 |
76 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) { | 76 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) { |
77 SealHandleScope shs(isolate); | 77 SealHandleScope shs(isolate); |
78 DCHECK(args.length() == 1); | 78 DCHECK(args.length() == 1); |
79 | 79 |
80 CONVERT_ARG_CHECKED(JSFunction, fun, 0); | 80 CONVERT_ARG_CHECKED(JSFunction, fun, 0); |
81 int pos = fun->shared()->start_position(); | 81 int pos = fun->shared()->start_position(); |
82 return Smi::FromInt(pos); | 82 return Smi::FromInt(pos); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 | 145 |
146 RUNTIME_FUNCTION(Runtime_SetCode) { | 146 RUNTIME_FUNCTION(Runtime_SetCode) { |
147 HandleScope scope(isolate); | 147 HandleScope scope(isolate); |
148 DCHECK(args.length() == 2); | 148 DCHECK(args.length() == 2); |
149 | 149 |
150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); | 150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); |
151 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1); | 151 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1); |
152 | 152 |
153 Handle<SharedFunctionInfo> target_shared(target->shared()); | 153 Handle<SharedFunctionInfo> target_shared(target->shared()); |
154 Handle<SharedFunctionInfo> source_shared(source->shared()); | 154 Handle<SharedFunctionInfo> source_shared(source->shared()); |
155 RUNTIME_ASSERT(!source_shared->bound()); | |
156 | 155 |
157 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { | 156 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { |
158 return isolate->heap()->exception(); | 157 return isolate->heap()->exception(); |
159 } | 158 } |
160 | 159 |
161 // Mark both, the source and the target, as un-flushable because the | 160 // Mark both, the source and the target, as un-flushable because the |
162 // shared unoptimized code makes them impossible to enqueue in a list. | 161 // shared unoptimized code makes them impossible to enqueue in a list. |
163 DCHECK(target_shared->code()->gc_metadata() == NULL); | 162 DCHECK(target_shared->code()->gc_metadata() == NULL); |
164 DCHECK(source_shared->code()->gc_metadata() == NULL); | 163 DCHECK(source_shared->code()->gc_metadata() == NULL); |
165 target_shared->set_dont_flush(true); | 164 target_shared->set_dont_flush(true); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 NewArray<Handle<Object> >(*total_argc)); | 301 NewArray<Handle<Object> >(*total_argc)); |
303 for (int i = 0; i < args_count; i++) { | 302 for (int i = 0; i < args_count; i++) { |
304 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); | 303 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); |
305 param_data[prefix_argc + i] = val; | 304 param_data[prefix_argc + i] = val; |
306 } | 305 } |
307 return param_data; | 306 return param_data; |
308 } | 307 } |
309 } | 308 } |
310 | 309 |
311 | 310 |
312 RUNTIME_FUNCTION(Runtime_FunctionBindArguments) { | |
313 HandleScope scope(isolate); | |
314 DCHECK(args.length() == 5); | |
315 CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0); | |
316 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, bindee, 1); | |
317 CONVERT_ARG_HANDLE_CHECKED(Object, this_object, 2); | |
318 CONVERT_NUMBER_ARG_HANDLE_CHECKED(new_length, 3); | |
319 CONVERT_ARG_HANDLE_CHECKED(Object, proto, 4); | |
320 | |
321 // TODO(lrn): Create bound function in C++ code from premade shared info. | |
322 bound_function->shared()->set_bound(true); | |
323 bound_function->shared()->set_optimized_code_map( | |
324 isolate->heap()->cleared_optimized_code_map()); | |
325 bound_function->shared()->set_inferred_name(isolate->heap()->empty_string()); | |
326 bound_function->shared()->set_construct_stub( | |
327 *isolate->builtins()->JSBuiltinsConstructStub()); | |
328 // Get all arguments of calling function (Function.prototype.bind). | |
329 int argc = 0; | |
330 base::SmartArrayPointer<Handle<Object>> arguments = | |
331 Runtime::GetCallerArguments(isolate, 0, &argc); | |
332 // Don't count the this-arg. | |
333 if (argc > 0) { | |
334 RUNTIME_ASSERT(arguments[0].is_identical_to(this_object)); | |
335 argc--; | |
336 } else { | |
337 RUNTIME_ASSERT(this_object->IsUndefined()); | |
338 } | |
339 // Initialize array of bindings (function, this, and any existing arguments | |
340 // if the function was already bound). | |
341 Handle<BindingsArray> new_bindings; | |
342 int out_index = 0; | |
343 Handle<TypeFeedbackVector> vector( | |
344 bound_function->shared()->feedback_vector()); | |
345 if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) { | |
346 Handle<BindingsArray> old_bindings( | |
347 JSFunction::cast(*bindee)->function_bindings()); | |
348 RUNTIME_ASSERT(old_bindings->bindings_count() >= 0); | |
349 bindee = handle(old_bindings->bound_function(), isolate); | |
350 Handle<Object> old_bound_this(old_bindings->bound_this(), isolate); | |
351 new_bindings = BindingsArray::New(isolate, vector, bindee, old_bound_this, | |
352 old_bindings->bindings_count() + argc); | |
353 for (int n = old_bindings->bindings_count(); out_index < n; out_index++) { | |
354 new_bindings->set_binding(out_index, old_bindings->binding(out_index)); | |
355 } | |
356 } else { | |
357 new_bindings = | |
358 BindingsArray::New(isolate, vector, bindee, this_object, argc); | |
359 } | |
360 // Copy arguments, skipping the first which is "this_arg". | |
361 for (int j = 0; j < argc; j++, out_index++) { | |
362 new_bindings->set_binding(out_index, *arguments[j + 1]); | |
363 } | |
364 new_bindings->set_map_no_write_barrier(isolate->heap()->fixed_array_map()); | |
365 bound_function->set_function_bindings(*new_bindings); | |
366 | |
367 // Update length. Have to remove the prototype first so that map migration | |
368 // is happy about the number of fields. | |
369 RUNTIME_ASSERT(bound_function->RemovePrototype()); | |
370 | |
371 // The new function should have the given prototype. | |
372 Handle<Map> bound_function_map = | |
373 bindee->IsConstructor() | |
374 ? isolate->bound_function_with_constructor_map() | |
375 : isolate->bound_function_without_constructor_map(); | |
376 if (bound_function_map->prototype() != *proto) { | |
377 bound_function_map = Map::TransitionToPrototype(bound_function_map, proto, | |
378 REGULAR_PROTOTYPE); | |
379 } | |
380 JSObject::MigrateToMap(bound_function, bound_function_map); | |
381 DCHECK_EQ(bindee->IsConstructor(), bound_function->IsConstructor()); | |
382 | |
383 Handle<String> length_string = isolate->factory()->length_string(); | |
384 // These attributes must be kept in sync with how the bootstrapper | |
385 // configures the bound_function_map retrieved above. | |
386 // We use ...IgnoreAttributes() here because of length's read-onliness. | |
387 PropertyAttributes attr = | |
388 static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY); | |
389 RETURN_FAILURE_ON_EXCEPTION( | |
390 isolate, JSObject::SetOwnPropertyIgnoreAttributes( | |
391 bound_function, length_string, new_length, attr)); | |
392 return *bound_function; | |
393 } | |
394 | |
395 | |
396 RUNTIME_FUNCTION(Runtime_BoundFunctionGetBindings) { | |
397 HandleScope handles(isolate); | |
398 DCHECK(args.length() == 1); | |
399 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0); | |
400 if (callable->IsJSFunction()) { | |
401 Handle<JSFunction> function = Handle<JSFunction>::cast(callable); | |
402 if (function->shared()->bound()) { | |
403 RUNTIME_ASSERT(function->function_bindings()->IsBindingsArray()); | |
404 Handle<BindingsArray> bindings(function->function_bindings()); | |
405 return *BindingsArray::CreateRuntimeBindings(bindings); | |
406 } | |
407 } | |
408 return isolate->heap()->undefined_value(); | |
409 } | |
410 | |
411 | |
412 RUNTIME_FUNCTION(Runtime_NewObjectFromBound) { | |
413 HandleScope scope(isolate); | |
414 DCHECK(args.length() == 1); | |
415 // First argument is a function to use as a constructor. | |
416 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | |
417 RUNTIME_ASSERT(function->shared()->bound()); | |
418 | |
419 // The argument is a bound function. Extract its bound arguments | |
420 // and callable. | |
421 Handle<BindingsArray> bound_args = | |
422 handle(BindingsArray::cast(function->function_bindings())); | |
423 int bound_argc = bound_args->bindings_count(); | |
424 Handle<Object> bound_function(bound_args->bound_function(), isolate); | |
425 DCHECK(!bound_function->IsJSFunction() || | |
426 !Handle<JSFunction>::cast(bound_function)->shared()->bound()); | |
427 | |
428 int total_argc = 0; | |
429 base::SmartArrayPointer<Handle<Object>> param_data = | |
430 Runtime::GetCallerArguments(isolate, bound_argc, &total_argc); | |
431 for (int i = 0; i < bound_argc; i++) { | |
432 param_data[i] = handle(bound_args->binding(i), isolate); | |
433 } | |
434 | |
435 Handle<Object> result; | |
436 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
437 isolate, result, Execution::New(isolate, bound_function, bound_function, | |
438 total_argc, param_data.get())); | |
439 return *result; | |
440 } | |
441 | |
442 | |
443 RUNTIME_FUNCTION(Runtime_Call) { | 311 RUNTIME_FUNCTION(Runtime_Call) { |
444 HandleScope scope(isolate); | 312 HandleScope scope(isolate); |
445 DCHECK_LE(2, args.length()); | 313 DCHECK_LE(2, args.length()); |
446 int const argc = args.length() - 2; | 314 int const argc = args.length() - 2; |
447 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); | 315 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); |
448 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); | 316 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); |
449 ScopedVector<Handle<Object>> argv(argc); | 317 ScopedVector<Handle<Object>> argv(argc); |
450 for (int i = 0; i < argc; ++i) { | 318 for (int i = 0; i < argc; ++i) { |
451 argv[i] = args.at<Object>(2 + i); | 319 argv[i] = args.at<Object>(2 + i); |
452 } | 320 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); | 388 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
521 if (receiver->IsNull() || receiver->IsUndefined()) { | 389 if (receiver->IsNull() || receiver->IsUndefined()) { |
522 return isolate->global_proxy(); | 390 return isolate->global_proxy(); |
523 } | 391 } |
524 return *Object::ToObject(isolate, receiver).ToHandleChecked(); | 392 return *Object::ToObject(isolate, receiver).ToHandleChecked(); |
525 } | 393 } |
526 | 394 |
527 | 395 |
528 RUNTIME_FUNCTION(Runtime_IsFunction) { | 396 RUNTIME_FUNCTION(Runtime_IsFunction) { |
529 SealHandleScope shs(isolate); | 397 SealHandleScope shs(isolate); |
530 DCHECK(args.length() == 1); | 398 DCHECK_EQ(1, args.length()); |
531 CONVERT_ARG_CHECKED(Object, obj, 0); | 399 CONVERT_ARG_CHECKED(Object, object, 0); |
532 return isolate->heap()->ToBoolean(obj->IsJSFunction()); | 400 return isolate->heap()->ToBoolean(object->IsFunction()); |
533 } | 401 } |
534 | 402 |
535 | 403 |
536 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { | 404 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { |
537 HandleScope scope(isolate); | 405 HandleScope scope(isolate); |
538 DCHECK(args.length() == 0); | 406 DCHECK(args.length() == 0); |
539 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 407 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
540 NewTypeError(MessageTemplate::kStrongArity)); | 408 NewTypeError(MessageTemplate::kStrongArity)); |
541 } | 409 } |
542 | 410 |
543 | 411 |
544 RUNTIME_FUNCTION(Runtime_FunctionToString) { | 412 RUNTIME_FUNCTION(Runtime_FunctionToString) { |
545 HandleScope scope(isolate); | 413 HandleScope scope(isolate); |
546 DCHECK_EQ(1, args.length()); | 414 DCHECK_EQ(1, args.length()); |
547 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 415 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); |
548 return *JSFunction::ToString(function); | 416 return function->IsJSBoundFunction() |
| 417 ? *JSBoundFunction::ToString( |
| 418 Handle<JSBoundFunction>::cast(function)) |
| 419 : *JSFunction::ToString(Handle<JSFunction>::cast(function)); |
549 } | 420 } |
550 | 421 |
551 } // namespace internal | 422 } // namespace internal |
552 } // namespace v8 | 423 } // namespace v8 |
OLD | NEW |