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_EQ(1, args.length()); | 56 DCHECK(args.length() == 1); |
57 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); | |
58 | 57 |
59 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value(); | 58 CONVERT_ARG_CHECKED(JSFunction, fun, 0); |
60 Handle<Object> script(Handle<JSFunction>::cast(function)->shared()->script(), | 59 Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate); |
61 isolate); | |
62 if (!script->IsScript()) return isolate->heap()->undefined_value(); | 60 if (!script->IsScript()) return isolate->heap()->undefined_value(); |
| 61 |
63 return *Script::GetWrapper(Handle<Script>::cast(script)); | 62 return *Script::GetWrapper(Handle<Script>::cast(script)); |
64 } | 63 } |
65 | 64 |
66 | 65 |
67 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { | 66 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) { |
68 HandleScope scope(isolate); | 67 HandleScope scope(isolate); |
69 DCHECK_EQ(1, args.length()); | 68 DCHECK(args.length() == 1); |
70 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); | 69 |
71 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value(); | 70 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0); |
72 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode(); | 71 Handle<SharedFunctionInfo> shared(f->shared()); |
| 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()); |
155 | 156 |
156 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { | 157 if (!Compiler::Compile(source, KEEP_EXCEPTION)) { |
157 return isolate->heap()->exception(); | 158 return isolate->heap()->exception(); |
158 } | 159 } |
159 | 160 |
160 // Mark both, the source and the target, as un-flushable because the | 161 // Mark both, the source and the target, as un-flushable because the |
161 // shared unoptimized code makes them impossible to enqueue in a list. | 162 // shared unoptimized code makes them impossible to enqueue in a list. |
162 DCHECK(target_shared->code()->gc_metadata() == NULL); | 163 DCHECK(target_shared->code()->gc_metadata() == NULL); |
163 DCHECK(source_shared->code()->gc_metadata() == NULL); | 164 DCHECK(source_shared->code()->gc_metadata() == NULL); |
164 target_shared->set_dont_flush(true); | 165 target_shared->set_dont_flush(true); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 NewArray<Handle<Object> >(*total_argc)); | 302 NewArray<Handle<Object> >(*total_argc)); |
302 for (int i = 0; i < args_count; i++) { | 303 for (int i = 0; i < args_count; i++) { |
303 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); | 304 Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate); |
304 param_data[prefix_argc + i] = val; | 305 param_data[prefix_argc + i] = val; |
305 } | 306 } |
306 return param_data; | 307 return param_data; |
307 } | 308 } |
308 } | 309 } |
309 | 310 |
310 | 311 |
| 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 |
311 RUNTIME_FUNCTION(Runtime_Call) { | 443 RUNTIME_FUNCTION(Runtime_Call) { |
312 HandleScope scope(isolate); | 444 HandleScope scope(isolate); |
313 DCHECK_LE(2, args.length()); | 445 DCHECK_LE(2, args.length()); |
314 int const argc = args.length() - 2; | 446 int const argc = args.length() - 2; |
315 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); | 447 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0); |
316 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); | 448 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1); |
317 ScopedVector<Handle<Object>> argv(argc); | 449 ScopedVector<Handle<Object>> argv(argc); |
318 for (int i = 0; i < argc; ++i) { | 450 for (int i = 0; i < argc; ++i) { |
319 argv[i] = args.at<Object>(2 + i); | 451 argv[i] = args.at<Object>(2 + i); |
320 } | 452 } |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); | 520 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0); |
389 if (receiver->IsNull() || receiver->IsUndefined()) { | 521 if (receiver->IsNull() || receiver->IsUndefined()) { |
390 return isolate->global_proxy(); | 522 return isolate->global_proxy(); |
391 } | 523 } |
392 return *Object::ToObject(isolate, receiver).ToHandleChecked(); | 524 return *Object::ToObject(isolate, receiver).ToHandleChecked(); |
393 } | 525 } |
394 | 526 |
395 | 527 |
396 RUNTIME_FUNCTION(Runtime_IsFunction) { | 528 RUNTIME_FUNCTION(Runtime_IsFunction) { |
397 SealHandleScope shs(isolate); | 529 SealHandleScope shs(isolate); |
398 DCHECK_EQ(1, args.length()); | 530 DCHECK(args.length() == 1); |
399 CONVERT_ARG_CHECKED(Object, object, 0); | 531 CONVERT_ARG_CHECKED(Object, obj, 0); |
400 return isolate->heap()->ToBoolean(object->IsFunction()); | 532 return isolate->heap()->ToBoolean(obj->IsJSFunction()); |
401 } | 533 } |
402 | 534 |
403 | 535 |
404 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { | 536 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) { |
405 HandleScope scope(isolate); | 537 HandleScope scope(isolate); |
406 DCHECK(args.length() == 0); | 538 DCHECK(args.length() == 0); |
407 THROW_NEW_ERROR_RETURN_FAILURE(isolate, | 539 THROW_NEW_ERROR_RETURN_FAILURE(isolate, |
408 NewTypeError(MessageTemplate::kStrongArity)); | 540 NewTypeError(MessageTemplate::kStrongArity)); |
409 } | 541 } |
410 | 542 |
411 | 543 |
412 RUNTIME_FUNCTION(Runtime_FunctionToString) { | 544 RUNTIME_FUNCTION(Runtime_FunctionToString) { |
413 HandleScope scope(isolate); | 545 HandleScope scope(isolate); |
414 DCHECK_EQ(1, args.length()); | 546 DCHECK_EQ(1, args.length()); |
415 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0); | 547 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); |
416 return function->IsJSBoundFunction() | 548 return *JSFunction::ToString(function); |
417 ? *JSBoundFunction::ToString( | |
418 Handle<JSBoundFunction>::cast(function)) | |
419 : *JSFunction::ToString(Handle<JSFunction>::cast(function)); | |
420 } | 549 } |
421 | 550 |
422 } // namespace internal | 551 } // namespace internal |
423 } // namespace v8 | 552 } // namespace v8 |
OLD | NEW |