OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/builtins/builtins.h" | 5 #include "src/builtins/builtins.h" |
6 | 6 |
7 #include "src/api-arguments.h" | 7 #include "src/api-arguments.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/api.h" | |
10 #include "src/base/ieee754.h" | 9 #include "src/base/ieee754.h" |
11 #include "src/base/once.h" | 10 #include "src/base/once.h" |
12 #include "src/bootstrapper.h" | 11 #include "src/bootstrapper.h" |
13 #include "src/code-factory.h" | 12 #include "src/code-factory.h" |
14 #include "src/code-stub-assembler.h" | 13 #include "src/code-stub-assembler.h" |
15 #include "src/dateparser-inl.h" | 14 #include "src/dateparser-inl.h" |
16 #include "src/elements.h" | 15 #include "src/elements.h" |
17 #include "src/frames-inl.h" | 16 #include "src/frames-inl.h" |
18 #include "src/gdb-jit.h" | 17 #include "src/gdb-jit.h" |
19 #include "src/globals.h" | 18 #include "src/globals.h" |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 assembler->Return(assembler->BooleanConstant(true)); | 381 assembler->Return(assembler->BooleanConstant(true)); |
383 | 382 |
384 assembler->Bind(&return_false); | 383 assembler->Bind(&return_false); |
385 assembler->Return(assembler->BooleanConstant(false)); | 384 assembler->Return(assembler->BooleanConstant(false)); |
386 | 385 |
387 assembler->Bind(&call_runtime); | 386 assembler->Bind(&call_runtime); |
388 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty, | 387 assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty, |
389 context, object, key)); | 388 context, object, key)); |
390 } | 389 } |
391 | 390 |
| 391 namespace { // anonymous namespace for ObjectProtoToString() |
| 392 |
| 393 void IsString(CodeStubAssembler* assembler, compiler::Node* object, |
| 394 CodeStubAssembler::Label* if_string, |
| 395 CodeStubAssembler::Label* if_notstring) { |
| 396 typedef compiler::Node Node; |
| 397 typedef CodeStubAssembler::Label Label; |
| 398 |
| 399 Label if_notsmi(assembler); |
| 400 assembler->Branch(assembler->WordIsSmi(object), if_notstring, &if_notsmi); |
| 401 |
| 402 assembler->Bind(&if_notsmi); |
| 403 { |
| 404 Node* instance_type = assembler->LoadInstanceType(object); |
| 405 |
| 406 assembler->Branch( |
| 407 assembler->Int32LessThan( |
| 408 instance_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 409 if_string, if_notstring); |
| 410 } |
| 411 } |
| 412 |
| 413 void ReturnToStringFormat(CodeStubAssembler* assembler, compiler::Node* context, |
| 414 compiler::Node* string) { |
| 415 typedef compiler::Node Node; |
| 416 |
| 417 Node* lhs = assembler->HeapConstant( |
| 418 assembler->factory()->NewStringFromStaticChars("[object ")); |
| 419 Node* rhs = assembler->HeapConstant( |
| 420 assembler->factory()->NewStringFromStaticChars("]")); |
| 421 |
| 422 Callable callable = CodeFactory::StringAdd( |
| 423 assembler->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED); |
| 424 |
| 425 assembler->Return(assembler->CallStub( |
| 426 callable, context, assembler->CallStub(callable, context, lhs, string), |
| 427 rhs)); |
| 428 } |
| 429 |
| 430 void ReturnIfPrimitive(CodeStubAssembler* assembler, |
| 431 compiler::Node* instance_type, |
| 432 CodeStubAssembler::Label* return_string, |
| 433 CodeStubAssembler::Label* return_boolean, |
| 434 CodeStubAssembler::Label* return_number) { |
| 435 assembler->GotoIf( |
| 436 assembler->Int32LessThan(instance_type, |
| 437 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 438 return_string); |
| 439 |
| 440 assembler->GotoIf(assembler->Word32Equal( |
| 441 instance_type, assembler->Int32Constant(ODDBALL_TYPE)), |
| 442 return_boolean); |
| 443 |
| 444 assembler->GotoIf( |
| 445 assembler->Word32Equal(instance_type, |
| 446 assembler->Int32Constant(HEAP_NUMBER_TYPE)), |
| 447 return_number); |
| 448 } |
| 449 |
| 450 } // namespace |
| 451 |
| 452 // ES6 section 19.1.3.6 Object.prototype.toString |
| 453 void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) { |
| 454 typedef compiler::Node Node; |
| 455 typedef CodeStubAssembler::Label Label; |
| 456 typedef CodeStubAssembler::Variable Variable; |
| 457 |
| 458 Label return_undefined(assembler, Label::kDeferred), |
| 459 return_null(assembler, Label::kDeferred), |
| 460 return_arguments(assembler, Label::kDeferred), return_array(assembler), |
| 461 return_api(assembler, Label::kDeferred), return_object(assembler), |
| 462 return_regexp(assembler), return_function(assembler), |
| 463 return_error(assembler), return_date(assembler), return_string(assembler), |
| 464 return_boolean(assembler), return_jsvalue(assembler), |
| 465 return_jsproxy(assembler, Label::kDeferred), return_number(assembler); |
| 466 |
| 467 Label if_isproxy(assembler, Label::kDeferred); |
| 468 |
| 469 Label checkstringtag(assembler); |
| 470 Label if_tostringtag(assembler), if_notostringtag(assembler); |
| 471 |
| 472 Node* receiver = assembler->Parameter(0); |
| 473 Node* context = assembler->Parameter(3); |
| 474 |
| 475 assembler->GotoIf( |
| 476 assembler->Word32Equal(receiver, assembler->UndefinedConstant()), |
| 477 &return_undefined); |
| 478 |
| 479 assembler->GotoIf(assembler->Word32Equal(receiver, assembler->NullConstant()), |
| 480 &return_null); |
| 481 |
| 482 assembler->GotoIf(assembler->WordIsSmi(receiver), &return_number); |
| 483 |
| 484 Node* receiver_instance_type = assembler->LoadInstanceType(receiver); |
| 485 ReturnIfPrimitive(assembler, receiver_instance_type, &return_string, |
| 486 &return_boolean, &return_number); |
| 487 |
| 488 // for proxies, check IsArray before getting @@toStringTag |
| 489 Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged); |
| 490 var_proxy_is_array.Bind(assembler->BooleanConstant(false)); |
| 491 |
| 492 assembler->Branch( |
| 493 assembler->Word32Equal(receiver_instance_type, |
| 494 assembler->Int32Constant(JS_PROXY_TYPE)), |
| 495 &if_isproxy, &checkstringtag); |
| 496 |
| 497 assembler->Bind(&if_isproxy); |
| 498 { |
| 499 // This can throw |
| 500 var_proxy_is_array.Bind( |
| 501 assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver)); |
| 502 assembler->Goto(&checkstringtag); |
| 503 } |
| 504 |
| 505 assembler->Bind(&checkstringtag); |
| 506 { |
| 507 Node* to_string_tag_symbol = assembler->HeapConstant( |
| 508 assembler->isolate()->factory()->to_string_tag_symbol()); |
| 509 |
| 510 GetPropertyStub stub(assembler->isolate()); |
| 511 Callable get_property = |
| 512 Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); |
| 513 Node* to_string_tag_value = assembler->CallStub( |
| 514 get_property, context, receiver, to_string_tag_symbol); |
| 515 |
| 516 IsString(assembler, to_string_tag_value, &if_tostringtag, |
| 517 &if_notostringtag); |
| 518 |
| 519 assembler->Bind(&if_tostringtag); |
| 520 ReturnToStringFormat(assembler, context, to_string_tag_value); |
| 521 } |
| 522 assembler->Bind(&if_notostringtag); |
| 523 { |
| 524 size_t const kNumCases = 11; |
| 525 Label* case_labels[kNumCases]; |
| 526 int32_t case_values[kNumCases]; |
| 527 case_labels[0] = &return_api; |
| 528 case_values[0] = JS_API_OBJECT_TYPE; |
| 529 case_labels[1] = &return_api; |
| 530 case_values[1] = JS_SPECIAL_API_OBJECT_TYPE; |
| 531 case_labels[2] = &return_arguments; |
| 532 case_values[2] = JS_ARGUMENTS_TYPE; |
| 533 case_labels[3] = &return_array; |
| 534 case_values[3] = JS_ARRAY_TYPE; |
| 535 case_labels[4] = &return_function; |
| 536 case_values[4] = JS_BOUND_FUNCTION_TYPE; |
| 537 case_labels[5] = &return_function; |
| 538 case_values[5] = JS_FUNCTION_TYPE; |
| 539 case_labels[6] = &return_error; |
| 540 case_values[6] = JS_ERROR_TYPE; |
| 541 case_labels[7] = &return_date; |
| 542 case_values[7] = JS_DATE_TYPE; |
| 543 case_labels[8] = &return_regexp; |
| 544 case_values[8] = JS_REGEXP_TYPE; |
| 545 case_labels[9] = &return_jsvalue; |
| 546 case_values[9] = JS_VALUE_TYPE; |
| 547 case_labels[10] = &return_jsproxy; |
| 548 case_values[10] = JS_PROXY_TYPE; |
| 549 |
| 550 assembler->Switch(receiver_instance_type, &return_object, case_values, |
| 551 case_labels, arraysize(case_values)); |
| 552 |
| 553 assembler->Bind(&return_undefined); |
| 554 assembler->Return(assembler->HeapConstant( |
| 555 assembler->isolate()->factory()->undefined_to_string())); |
| 556 |
| 557 assembler->Bind(&return_null); |
| 558 assembler->Return(assembler->HeapConstant( |
| 559 assembler->isolate()->factory()->null_to_string())); |
| 560 |
| 561 assembler->Bind(&return_number); |
| 562 assembler->Return(assembler->HeapConstant( |
| 563 assembler->isolate()->factory()->number_to_string())); |
| 564 |
| 565 assembler->Bind(&return_string); |
| 566 assembler->Return(assembler->HeapConstant( |
| 567 assembler->isolate()->factory()->string_to_string())); |
| 568 |
| 569 assembler->Bind(&return_boolean); |
| 570 assembler->Return(assembler->HeapConstant( |
| 571 assembler->isolate()->factory()->boolean_to_string())); |
| 572 |
| 573 assembler->Bind(&return_arguments); |
| 574 assembler->Return(assembler->HeapConstant( |
| 575 assembler->isolate()->factory()->arguments_to_string())); |
| 576 |
| 577 assembler->Bind(&return_array); |
| 578 assembler->Return(assembler->HeapConstant( |
| 579 assembler->isolate()->factory()->array_to_string())); |
| 580 |
| 581 assembler->Bind(&return_function); |
| 582 assembler->Return(assembler->HeapConstant( |
| 583 assembler->isolate()->factory()->function_to_string())); |
| 584 |
| 585 assembler->Bind(&return_error); |
| 586 assembler->Return(assembler->HeapConstant( |
| 587 assembler->isolate()->factory()->error_to_string())); |
| 588 |
| 589 assembler->Bind(&return_date); |
| 590 assembler->Return(assembler->HeapConstant( |
| 591 assembler->isolate()->factory()->date_to_string())); |
| 592 |
| 593 assembler->Bind(&return_regexp); |
| 594 assembler->Return(assembler->HeapConstant( |
| 595 assembler->isolate()->factory()->regexp_to_string())); |
| 596 |
| 597 assembler->Bind(&return_api); |
| 598 { |
| 599 Node* class_name = |
| 600 assembler->CallRuntime(Runtime::kClassOf, context, receiver); |
| 601 ReturnToStringFormat(assembler, context, class_name); |
| 602 } |
| 603 |
| 604 assembler->Bind(&return_jsvalue); |
| 605 { |
| 606 Node* value = assembler->LoadJSValueValue(receiver); |
| 607 assembler->GotoIf(assembler->WordIsSmi(value), &return_number); |
| 608 |
| 609 ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value), |
| 610 &return_string, &return_boolean, &return_number); |
| 611 assembler->Goto(&return_object); |
| 612 } |
| 613 |
| 614 assembler->Bind(&return_jsproxy); |
| 615 { |
| 616 assembler->GotoIf(assembler->WordEqual(var_proxy_is_array.value(), |
| 617 assembler->BooleanConstant(true)), |
| 618 &return_array); |
| 619 |
| 620 Node* map = assembler->LoadMap(receiver); |
| 621 |
| 622 // Return object if the proxy {receiver} is not callable. |
| 623 assembler->Branch( |
| 624 assembler->Word32Equal( |
| 625 assembler->Word32And( |
| 626 assembler->LoadMapBitField(map), |
| 627 assembler->Int32Constant(1 << Map::kIsCallable)), |
| 628 assembler->Int32Constant(0)), |
| 629 &return_object, &return_function); |
| 630 } |
| 631 |
| 632 // Default |
| 633 assembler->Bind(&return_object); |
| 634 assembler->Return(assembler->HeapConstant( |
| 635 assembler->isolate()->factory()->object_to_string())); |
| 636 } |
| 637 } |
| 638 |
392 namespace { | 639 namespace { |
393 | 640 |
394 Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) { | 641 Object* DoArrayPush(Isolate* isolate, BuiltinArguments args) { |
395 HandleScope scope(isolate); | 642 HandleScope scope(isolate); |
396 Handle<Object> receiver = args.receiver(); | 643 Handle<Object> receiver = args.receiver(); |
397 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) { | 644 if (!EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1)) { |
398 return CallJsIntrinsic(isolate, isolate->array_push(), args); | 645 return CallJsIntrinsic(isolate, isolate->array_push(), args); |
399 } | 646 } |
400 // Fast Elements Path | 647 // Fast Elements Path |
401 int to_add = args.length() - 1; | 648 int to_add = args.length() - 1; |
(...skipping 4484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4886 isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1))); | 5133 isolate, name, Object::ToName(isolate, args.atOrUndefined(isolate, 1))); |
4887 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 5134 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
4888 isolate, object, JSReceiver::ToObject(isolate, args.receiver())); | 5135 isolate, object, JSReceiver::ToObject(isolate, args.receiver())); |
4889 Maybe<PropertyAttributes> maybe = | 5136 Maybe<PropertyAttributes> maybe = |
4890 JSReceiver::GetOwnPropertyAttributes(object, name); | 5137 JSReceiver::GetOwnPropertyAttributes(object, name); |
4891 if (!maybe.IsJust()) return isolate->heap()->exception(); | 5138 if (!maybe.IsJust()) return isolate->heap()->exception(); |
4892 if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value(); | 5139 if (maybe.FromJust() == ABSENT) return isolate->heap()->false_value(); |
4893 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0); | 5140 return isolate->heap()->ToBoolean((maybe.FromJust() & DONT_ENUM) == 0); |
4894 } | 5141 } |
4895 | 5142 |
4896 // ES6 section 19.1.3.6 Object.prototype.toString | |
4897 BUILTIN(ObjectProtoToString) { | |
4898 HandleScope scope(isolate); | |
4899 Handle<Object> object = args.at<Object>(0); | |
4900 RETURN_RESULT_OR_FAILURE(isolate, | |
4901 Object::ObjectProtoToString(isolate, object)); | |
4902 } | |
4903 | |
4904 // ----------------------------------------------------------------------------- | 5143 // ----------------------------------------------------------------------------- |
4905 // ES6 section 19.4 Symbol Objects | 5144 // ES6 section 19.4 Symbol Objects |
4906 | 5145 |
4907 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case. | 5146 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case. |
4908 BUILTIN(SymbolConstructor) { | 5147 BUILTIN(SymbolConstructor) { |
4909 HandleScope scope(isolate); | 5148 HandleScope scope(isolate); |
4910 Handle<Symbol> result = isolate->factory()->NewSymbol(); | 5149 Handle<Symbol> result = isolate->factory()->NewSymbol(); |
4911 Handle<Object> description = args.atOrUndefined(isolate, 1); | 5150 Handle<Object> description = args.atOrUndefined(isolate, 1); |
4912 if (!description->IsUndefined(isolate)) { | 5151 if (!description->IsUndefined(isolate)) { |
4913 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description, | 5152 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description, |
(...skipping 2009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6923 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ | 7162 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ |
6924 Handle<Code> Builtins::Name() { \ | 7163 Handle<Code> Builtins::Name() { \ |
6925 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ | 7164 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ |
6926 return Handle<Code>(code_address); \ | 7165 return Handle<Code>(code_address); \ |
6927 } | 7166 } |
6928 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) | 7167 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) |
6929 #undef DEFINE_BUILTIN_ACCESSOR | 7168 #undef DEFINE_BUILTIN_ACCESSOR |
6930 | 7169 |
6931 } // namespace internal | 7170 } // namespace internal |
6932 } // namespace v8 | 7171 } // namespace v8 |
OLD | NEW |