| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 #include "cpu.h" | 38 #include "cpu.h" |
| 39 #include "dateparser-inl.h" | 39 #include "dateparser-inl.h" |
| 40 #include "debug.h" | 40 #include "debug.h" |
| 41 #include "deoptimizer.h" | 41 #include "deoptimizer.h" |
| 42 #include "execution.h" | 42 #include "execution.h" |
| 43 #include "global-handles.h" | 43 #include "global-handles.h" |
| 44 #include "jsregexp.h" | 44 #include "jsregexp.h" |
| 45 #include "json-parser.h" | 45 #include "json-parser.h" |
| 46 #include "liveedit.h" | 46 #include "liveedit.h" |
| 47 #include "liveobjectlist-inl.h" | 47 #include "liveobjectlist-inl.h" |
| 48 #include "misc-intrinsics.h" |
| 48 #include "parser.h" | 49 #include "parser.h" |
| 49 #include "platform.h" | 50 #include "platform.h" |
| 50 #include "runtime-profiler.h" | 51 #include "runtime-profiler.h" |
| 51 #include "runtime.h" | 52 #include "runtime.h" |
| 52 #include "scopeinfo.h" | 53 #include "scopeinfo.h" |
| 53 #include "smart-pointer.h" | 54 #include "smart-pointer.h" |
| 54 #include "string-search.h" | 55 #include "string-search.h" |
| 55 #include "stub-cache.h" | 56 #include "stub-cache.h" |
| 56 #include "v8threads.h" | 57 #include "v8threads.h" |
| 57 #include "vm-state-inl.h" | 58 #include "vm-state-inl.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 74 RUNTIME_ASSERT(args[index]->Is##Type()); \ | 75 RUNTIME_ASSERT(args[index]->Is##Type()); \ |
| 75 Handle<Type> name = args.at<Type>(index); | 76 Handle<Type> name = args.at<Type>(index); |
| 76 | 77 |
| 77 // Cast the given object to a boolean and store it in a variable with | 78 // Cast the given object to a boolean and store it in a variable with |
| 78 // the given name. If the object is not a boolean call IllegalOperation | 79 // the given name. If the object is not a boolean call IllegalOperation |
| 79 // and return. | 80 // and return. |
| 80 #define CONVERT_BOOLEAN_CHECKED(name, obj) \ | 81 #define CONVERT_BOOLEAN_CHECKED(name, obj) \ |
| 81 RUNTIME_ASSERT(obj->IsBoolean()); \ | 82 RUNTIME_ASSERT(obj->IsBoolean()); \ |
| 82 bool name = (obj)->IsTrue(); | 83 bool name = (obj)->IsTrue(); |
| 83 | 84 |
| 84 // Cast the given object to a Smi and store its value in an int variable | 85 // Cast the given argument to a Smi and store its value in an int variable |
| 85 // with the given name. If the object is not a Smi call IllegalOperation | 86 // with the given name. If the argument is not a Smi call IllegalOperation |
| 86 // and return. | 87 // and return. |
| 87 #define CONVERT_SMI_CHECKED(name, obj) \ | 88 #define CONVERT_SMI_ARG_CHECKED(name, index) \ |
| 88 RUNTIME_ASSERT(obj->IsSmi()); \ | 89 RUNTIME_ASSERT(args[index]->IsSmi()); \ |
| 89 int name = Smi::cast(obj)->value(); | 90 int name = args.smi_at(index); |
| 90 | 91 |
| 91 // Cast the given object to a double and store it in a variable with | 92 // Cast the given argument to a double and store it in a variable with |
| 92 // the given name. If the object is not a number (as opposed to | 93 // the given name. If the argument is not a number (as opposed to |
| 93 // the number not-a-number) call IllegalOperation and return. | 94 // the number not-a-number) call IllegalOperation and return. |
| 94 #define CONVERT_DOUBLE_CHECKED(name, obj) \ | 95 #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \ |
| 95 RUNTIME_ASSERT(obj->IsNumber()); \ | 96 RUNTIME_ASSERT(args[index]->IsNumber()); \ |
| 96 double name = (obj)->Number(); | 97 double name = args.number_at(index); |
| 97 | 98 |
| 98 // Call the specified converter on the object *comand store the result in | 99 // Call the specified converter on the object *comand store the result in |
| 99 // a variable of the specified type with the given name. If the | 100 // a variable of the specified type with the given name. If the |
| 100 // object is not a Number call IllegalOperation and return. | 101 // object is not a Number call IllegalOperation and return. |
| 101 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ | 102 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ |
| 102 RUNTIME_ASSERT(obj->IsNumber()); \ | 103 RUNTIME_ASSERT(obj->IsNumber()); \ |
| 103 type name = NumberTo##Type(obj); | 104 type name = NumberTo##Type(obj); |
| 104 | 105 |
| 105 | 106 |
| 106 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, | 107 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 | 476 |
| 476 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralBoilerplate) { | 477 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralBoilerplate) { |
| 477 // Takes a FixedArray of elements containing the literal elements of | 478 // Takes a FixedArray of elements containing the literal elements of |
| 478 // the array literal and produces JSArray with those elements. | 479 // the array literal and produces JSArray with those elements. |
| 479 // Additionally takes the literals array of the surrounding function | 480 // Additionally takes the literals array of the surrounding function |
| 480 // which contains the context from which to get the Array function | 481 // which contains the context from which to get the Array function |
| 481 // to use for creating the array literal. | 482 // to use for creating the array literal. |
| 482 HandleScope scope(isolate); | 483 HandleScope scope(isolate); |
| 483 ASSERT(args.length() == 3); | 484 ASSERT(args.length() == 3); |
| 484 CONVERT_ARG_CHECKED(FixedArray, literals, 0); | 485 CONVERT_ARG_CHECKED(FixedArray, literals, 0); |
| 485 CONVERT_SMI_CHECKED(literals_index, args[1]); | 486 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
| 486 CONVERT_ARG_CHECKED(FixedArray, elements, 2); | 487 CONVERT_ARG_CHECKED(FixedArray, elements, 2); |
| 487 | 488 |
| 488 Handle<Object> object = | 489 Handle<Object> object = |
| 489 CreateArrayLiteralBoilerplate(isolate, literals, elements); | 490 CreateArrayLiteralBoilerplate(isolate, literals, elements); |
| 490 if (object.is_null()) return Failure::Exception(); | 491 if (object.is_null()) return Failure::Exception(); |
| 491 | 492 |
| 492 // Update the functions literal and return the boilerplate. | 493 // Update the functions literal and return the boilerplate. |
| 493 literals->set(literals_index, *object); | 494 literals->set(literals_index, *object); |
| 494 return *object; | 495 return *object; |
| 495 } | 496 } |
| 496 | 497 |
| 497 | 498 |
| 498 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) { | 499 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) { |
| 499 HandleScope scope(isolate); | 500 HandleScope scope(isolate); |
| 500 ASSERT(args.length() == 4); | 501 ASSERT(args.length() == 4); |
| 501 CONVERT_ARG_CHECKED(FixedArray, literals, 0); | 502 CONVERT_ARG_CHECKED(FixedArray, literals, 0); |
| 502 CONVERT_SMI_CHECKED(literals_index, args[1]); | 503 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
| 503 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); | 504 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); |
| 504 CONVERT_SMI_CHECKED(flags, args[3]); | 505 CONVERT_SMI_ARG_CHECKED(flags, 3); |
| 505 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; | 506 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; |
| 506 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; | 507 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; |
| 507 | 508 |
| 508 // Check if boilerplate exists. If not, create it first. | 509 // Check if boilerplate exists. If not, create it first. |
| 509 Handle<Object> boilerplate(literals->get(literals_index), isolate); | 510 Handle<Object> boilerplate(literals->get(literals_index), isolate); |
| 510 if (*boilerplate == isolate->heap()->undefined_value()) { | 511 if (*boilerplate == isolate->heap()->undefined_value()) { |
| 511 boilerplate = CreateObjectLiteralBoilerplate(isolate, | 512 boilerplate = CreateObjectLiteralBoilerplate(isolate, |
| 512 literals, | 513 literals, |
| 513 constant_properties, | 514 constant_properties, |
| 514 should_have_fast_elements, | 515 should_have_fast_elements, |
| 515 has_function_literal); | 516 has_function_literal); |
| 516 if (boilerplate.is_null()) return Failure::Exception(); | 517 if (boilerplate.is_null()) return Failure::Exception(); |
| 517 // Update the functions literal and return the boilerplate. | 518 // Update the functions literal and return the boilerplate. |
| 518 literals->set(literals_index, *boilerplate); | 519 literals->set(literals_index, *boilerplate); |
| 519 } | 520 } |
| 520 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); | 521 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); |
| 521 } | 522 } |
| 522 | 523 |
| 523 | 524 |
| 524 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) { | 525 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) { |
| 525 HandleScope scope(isolate); | 526 HandleScope scope(isolate); |
| 526 ASSERT(args.length() == 4); | 527 ASSERT(args.length() == 4); |
| 527 CONVERT_ARG_CHECKED(FixedArray, literals, 0); | 528 CONVERT_ARG_CHECKED(FixedArray, literals, 0); |
| 528 CONVERT_SMI_CHECKED(literals_index, args[1]); | 529 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
| 529 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); | 530 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); |
| 530 CONVERT_SMI_CHECKED(flags, args[3]); | 531 CONVERT_SMI_ARG_CHECKED(flags, 3); |
| 531 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; | 532 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; |
| 532 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; | 533 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; |
| 533 | 534 |
| 534 // Check if boilerplate exists. If not, create it first. | 535 // Check if boilerplate exists. If not, create it first. |
| 535 Handle<Object> boilerplate(literals->get(literals_index), isolate); | 536 Handle<Object> boilerplate(literals->get(literals_index), isolate); |
| 536 if (*boilerplate == isolate->heap()->undefined_value()) { | 537 if (*boilerplate == isolate->heap()->undefined_value()) { |
| 537 boilerplate = CreateObjectLiteralBoilerplate(isolate, | 538 boilerplate = CreateObjectLiteralBoilerplate(isolate, |
| 538 literals, | 539 literals, |
| 539 constant_properties, | 540 constant_properties, |
| 540 should_have_fast_elements, | 541 should_have_fast_elements, |
| 541 has_function_literal); | 542 has_function_literal); |
| 542 if (boilerplate.is_null()) return Failure::Exception(); | 543 if (boilerplate.is_null()) return Failure::Exception(); |
| 543 // Update the functions literal and return the boilerplate. | 544 // Update the functions literal and return the boilerplate. |
| 544 literals->set(literals_index, *boilerplate); | 545 literals->set(literals_index, *boilerplate); |
| 545 } | 546 } |
| 546 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); | 547 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); |
| 547 } | 548 } |
| 548 | 549 |
| 549 | 550 |
| 550 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) { | 551 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) { |
| 551 HandleScope scope(isolate); | 552 HandleScope scope(isolate); |
| 552 ASSERT(args.length() == 3); | 553 ASSERT(args.length() == 3); |
| 553 CONVERT_ARG_CHECKED(FixedArray, literals, 0); | 554 CONVERT_ARG_CHECKED(FixedArray, literals, 0); |
| 554 CONVERT_SMI_CHECKED(literals_index, args[1]); | 555 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
| 555 CONVERT_ARG_CHECKED(FixedArray, elements, 2); | 556 CONVERT_ARG_CHECKED(FixedArray, elements, 2); |
| 556 | 557 |
| 557 // Check if boilerplate exists. If not, create it first. | 558 // Check if boilerplate exists. If not, create it first. |
| 558 Handle<Object> boilerplate(literals->get(literals_index), isolate); | 559 Handle<Object> boilerplate(literals->get(literals_index), isolate); |
| 559 if (*boilerplate == isolate->heap()->undefined_value()) { | 560 if (*boilerplate == isolate->heap()->undefined_value()) { |
| 560 boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements); | 561 boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements); |
| 561 if (boilerplate.is_null()) return Failure::Exception(); | 562 if (boilerplate.is_null()) return Failure::Exception(); |
| 562 // Update the functions literal and return the boilerplate. | 563 // Update the functions literal and return the boilerplate. |
| 563 literals->set(literals_index, *boilerplate); | 564 literals->set(literals_index, *boilerplate); |
| 564 } | 565 } |
| 565 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); | 566 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); |
| 566 } | 567 } |
| 567 | 568 |
| 568 | 569 |
| 569 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { | 570 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { |
| 570 HandleScope scope(isolate); | 571 HandleScope scope(isolate); |
| 571 ASSERT(args.length() == 3); | 572 ASSERT(args.length() == 3); |
| 572 CONVERT_ARG_CHECKED(FixedArray, literals, 0); | 573 CONVERT_ARG_CHECKED(FixedArray, literals, 0); |
| 573 CONVERT_SMI_CHECKED(literals_index, args[1]); | 574 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
| 574 CONVERT_ARG_CHECKED(FixedArray, elements, 2); | 575 CONVERT_ARG_CHECKED(FixedArray, elements, 2); |
| 575 | 576 |
| 576 // Check if boilerplate exists. If not, create it first. | 577 // Check if boilerplate exists. If not, create it first. |
| 577 Handle<Object> boilerplate(literals->get(literals_index), isolate); | 578 Handle<Object> boilerplate(literals->get(literals_index), isolate); |
| 578 if (*boilerplate == isolate->heap()->undefined_value()) { | 579 if (*boilerplate == isolate->heap()->undefined_value()) { |
| 579 boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements); | 580 boilerplate = CreateArrayLiteralBoilerplate(isolate, literals, elements); |
| 580 if (boilerplate.is_null()) return Failure::Exception(); | 581 if (boilerplate.is_null()) return Failure::Exception(); |
| 581 // Update the functions literal and return the boilerplate. | 582 // Update the functions literal and return the boilerplate. |
| 582 literals->set(literals_index, *boilerplate); | 583 literals->set(literals_index, *boilerplate); |
| 583 } | 584 } |
| 584 if (JSObject::cast(*boilerplate)->elements()->map() == | 585 if (JSObject::cast(*boilerplate)->elements()->map() == |
| 585 isolate->heap()->fixed_cow_array_map()) { | 586 isolate->heap()->fixed_cow_array_map()) { |
| 586 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 587 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
| 587 } | 588 } |
| 588 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); | 589 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); |
| 589 } | 590 } |
| 590 | 591 |
| 591 | 592 |
| 592 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) { | 593 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) { |
| 593 ASSERT(args.length() == 2); | 594 ASSERT(args.length() == 2); |
| 594 Object* handler = args[0]; | 595 Object* handler = args[0]; |
| 595 Object* prototype = args[1]; | 596 Object* prototype = args[1]; |
| 596 Object* used_prototype = | 597 Object* used_prototype = |
| 597 (prototype->IsJSObject() || prototype->IsJSProxy()) ? prototype | 598 prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value(); |
| 598 : isolate->heap()->null_value(); | |
| 599 return isolate->heap()->AllocateJSProxy(handler, used_prototype); | 599 return isolate->heap()->AllocateJSProxy(handler, used_prototype); |
| 600 } | 600 } |
| 601 | 601 |
| 602 | 602 |
| 603 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCatchExtensionObject) { | 603 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) { |
| 604 ASSERT(args.length() == 2); | 604 ASSERT(args.length() == 1); |
| 605 CONVERT_CHECKED(String, key, args[0]); | 605 Object* obj = args[0]; |
| 606 Object* value = args[1]; | 606 return obj->IsJSProxy() |
| 607 RUNTIME_ASSERT(!value->IsFailure()); | 607 ? isolate->heap()->true_value() : isolate->heap()->false_value(); |
| 608 // Create a catch context extension object. | 608 } |
| 609 JSFunction* constructor = | 609 |
| 610 isolate->context()->global_context()-> | 610 |
| 611 context_extension_function(); | 611 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) { |
| 612 Object* object; | 612 ASSERT(args.length() == 1); |
| 613 { MaybeObject* maybe_object = isolate->heap()->AllocateJSObject(constructor); | 613 CONVERT_CHECKED(JSProxy, proxy, args[0]); |
| 614 if (!maybe_object->ToObject(&object)) return maybe_object; | 614 return proxy->handler(); |
| 615 } | |
| 616 // Assign the exception value to the catch variable and make sure | |
| 617 // that the catch variable is DontDelete. | |
| 618 { MaybeObject* maybe_value = | |
| 619 // Passing non-strict per ECMA-262 5th Ed. 12.14. Catch, bullet #4. | |
| 620 JSObject::cast(object)->SetProperty( | |
| 621 key, value, DONT_DELETE, kNonStrictMode); | |
| 622 if (!maybe_value->ToObject(&value)) return maybe_value; | |
| 623 } | |
| 624 return object; | |
| 625 } | 615 } |
| 626 | 616 |
| 627 | 617 |
| 628 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) { | 618 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) { |
| 629 NoHandleAllocation ha; | 619 NoHandleAllocation ha; |
| 630 ASSERT(args.length() == 1); | 620 ASSERT(args.length() == 1); |
| 631 Object* obj = args[0]; | 621 Object* obj = args[0]; |
| 632 if (!obj->IsJSObject()) return isolate->heap()->null_value(); | 622 if (!obj->IsJSObject()) return isolate->heap()->null_value(); |
| 633 return JSObject::cast(obj)->class_name(); | 623 return JSObject::cast(obj)->class_name(); |
| 634 } | 624 } |
| 635 | 625 |
| 636 | 626 |
| 627 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) { |
| 628 NoHandleAllocation ha; |
| 629 ASSERT(args.length() == 1); |
| 630 Object* obj = args[0]; |
| 631 do { |
| 632 obj = obj->GetPrototype(); |
| 633 } while (obj->IsJSObject() && |
| 634 JSObject::cast(obj)->map()->is_hidden_prototype()); |
| 635 return obj; |
| 636 } |
| 637 |
| 638 |
| 637 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) { | 639 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) { |
| 638 NoHandleAllocation ha; | 640 NoHandleAllocation ha; |
| 639 ASSERT(args.length() == 2); | 641 ASSERT(args.length() == 2); |
| 640 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). | 642 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). |
| 641 Object* O = args[0]; | 643 Object* O = args[0]; |
| 642 Object* V = args[1]; | 644 Object* V = args[1]; |
| 643 while (true) { | 645 while (true) { |
| 644 Object* prototype = V->GetPrototype(); | 646 Object* prototype = V->GetPrototype(); |
| 645 if (prototype->IsNull()) return isolate->heap()->false_value(); | 647 if (prototype->IsNull()) return isolate->heap()->false_value(); |
| 646 if (O == prototype) return isolate->heap()->true_value(); | 648 if (O == prototype) return isolate->heap()->true_value(); |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 } | 869 } |
| 868 | 870 |
| 869 case JSObject::DICTIONARY_ELEMENT: { | 871 case JSObject::DICTIONARY_ELEMENT: { |
| 870 Handle<JSObject> holder = obj; | 872 Handle<JSObject> holder = obj; |
| 871 if (obj->IsJSGlobalProxy()) { | 873 if (obj->IsJSGlobalProxy()) { |
| 872 Object* proto = obj->GetPrototype(); | 874 Object* proto = obj->GetPrototype(); |
| 873 if (proto->IsNull()) return heap->undefined_value(); | 875 if (proto->IsNull()) return heap->undefined_value(); |
| 874 ASSERT(proto->IsJSGlobalObject()); | 876 ASSERT(proto->IsJSGlobalObject()); |
| 875 holder = Handle<JSObject>(JSObject::cast(proto)); | 877 holder = Handle<JSObject>(JSObject::cast(proto)); |
| 876 } | 878 } |
| 877 NumberDictionary* dictionary = holder->element_dictionary(); | 879 FixedArray* elements = FixedArray::cast(holder->elements()); |
| 880 NumberDictionary* dictionary = NULL; |
| 881 if (elements->map() == heap->non_strict_arguments_elements_map()) { |
| 882 dictionary = NumberDictionary::cast(elements->get(1)); |
| 883 } else { |
| 884 dictionary = NumberDictionary::cast(elements); |
| 885 } |
| 878 int entry = dictionary->FindEntry(index); | 886 int entry = dictionary->FindEntry(index); |
| 879 ASSERT(entry != NumberDictionary::kNotFound); | 887 ASSERT(entry != NumberDictionary::kNotFound); |
| 880 PropertyDetails details = dictionary->DetailsAt(entry); | 888 PropertyDetails details = dictionary->DetailsAt(entry); |
| 881 switch (details.type()) { | 889 switch (details.type()) { |
| 882 case CALLBACKS: { | 890 case CALLBACKS: { |
| 883 // This is an accessor property with getter and/or setter. | 891 // This is an accessor property with getter and/or setter. |
| 884 FixedArray* callbacks = | 892 FixedArray* callbacks = |
| 885 FixedArray::cast(dictionary->ValueAt(entry)); | 893 FixedArray::cast(dictionary->ValueAt(entry)); |
| 886 elms->set(IS_ACCESSOR_INDEX, heap->true_value()); | 894 elms->set(IS_ACCESSOR_INDEX, heap->true_value()); |
| 887 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { | 895 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 | 1085 |
| 1078 | 1086 |
| 1079 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { | 1087 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { |
| 1080 ASSERT(args.length() == 4); | 1088 ASSERT(args.length() == 4); |
| 1081 HandleScope scope(isolate); | 1089 HandleScope scope(isolate); |
| 1082 Handle<GlobalObject> global = Handle<GlobalObject>( | 1090 Handle<GlobalObject> global = Handle<GlobalObject>( |
| 1083 isolate->context()->global()); | 1091 isolate->context()->global()); |
| 1084 | 1092 |
| 1085 Handle<Context> context = args.at<Context>(0); | 1093 Handle<Context> context = args.at<Context>(0); |
| 1086 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); | 1094 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); |
| 1087 bool is_eval = Smi::cast(args[2])->value() == 1; | 1095 bool is_eval = args.smi_at(2) == 1; |
| 1088 StrictModeFlag strict_mode = | 1096 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3)); |
| 1089 static_cast<StrictModeFlag>(Smi::cast(args[3])->value()); | |
| 1090 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); | 1097 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); |
| 1091 | 1098 |
| 1092 // Compute the property attributes. According to ECMA-262, section | 1099 // Compute the property attributes. According to ECMA-262, section |
| 1093 // 13, page 71, the property must be read-only and | 1100 // 13, page 71, the property must be read-only and |
| 1094 // non-deletable. However, neither SpiderMonkey nor KJS creates the | 1101 // non-deletable. However, neither SpiderMonkey nor KJS creates the |
| 1095 // property as read-only, so we don't either. | 1102 // property as read-only, so we don't either. |
| 1096 PropertyAttributes base = is_eval ? NONE : DONT_DELETE; | 1103 PropertyAttributes base = is_eval ? NONE : DONT_DELETE; |
| 1097 | 1104 |
| 1098 // Traverse the name/value pairs and set the properties. | 1105 // Traverse the name/value pairs and set the properties. |
| 1099 int length = pairs->length(); | 1106 int length = pairs->length(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 return isolate->heap()->undefined_value(); | 1225 return isolate->heap()->undefined_value(); |
| 1219 } | 1226 } |
| 1220 | 1227 |
| 1221 | 1228 |
| 1222 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { | 1229 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { |
| 1223 HandleScope scope(isolate); | 1230 HandleScope scope(isolate); |
| 1224 ASSERT(args.length() == 4); | 1231 ASSERT(args.length() == 4); |
| 1225 | 1232 |
| 1226 CONVERT_ARG_CHECKED(Context, context, 0); | 1233 CONVERT_ARG_CHECKED(Context, context, 0); |
| 1227 Handle<String> name(String::cast(args[1])); | 1234 Handle<String> name(String::cast(args[1])); |
| 1228 PropertyAttributes mode = | 1235 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); |
| 1229 static_cast<PropertyAttributes>(Smi::cast(args[2])->value()); | |
| 1230 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); | 1236 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); |
| 1231 Handle<Object> initial_value(args[3], isolate); | 1237 Handle<Object> initial_value(args[3], isolate); |
| 1232 | 1238 |
| 1233 // Declarations are always done in the function context. | 1239 // Declarations are always done in a function or global context. |
| 1234 context = Handle<Context>(context->fcontext()); | 1240 context = Handle<Context>(context->declaration_context()); |
| 1235 | 1241 |
| 1236 int index; | 1242 int index; |
| 1237 PropertyAttributes attributes; | 1243 PropertyAttributes attributes; |
| 1238 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; | 1244 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; |
| 1239 Handle<Object> holder = | 1245 Handle<Object> holder = |
| 1240 context->Lookup(name, flags, &index, &attributes); | 1246 context->Lookup(name, flags, &index, &attributes); |
| 1241 | 1247 |
| 1242 if (attributes != ABSENT) { | 1248 if (attributes != ABSENT) { |
| 1243 // The name was declared before; check for conflicting | 1249 // The name was declared before; check for conflicting |
| 1244 // re-declarations: This is similar to the code in parser.cc in | 1250 // re-declarations: This is similar to the code in parser.cc in |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 } | 1284 } |
| 1279 } | 1285 } |
| 1280 | 1286 |
| 1281 } else { | 1287 } else { |
| 1282 // The property is not in the function context. It needs to be | 1288 // The property is not in the function context. It needs to be |
| 1283 // "declared" in the function context's extension context, or in the | 1289 // "declared" in the function context's extension context, or in the |
| 1284 // global context. | 1290 // global context. |
| 1285 Handle<JSObject> context_ext; | 1291 Handle<JSObject> context_ext; |
| 1286 if (context->has_extension()) { | 1292 if (context->has_extension()) { |
| 1287 // The function context's extension context exists - use it. | 1293 // The function context's extension context exists - use it. |
| 1288 context_ext = Handle<JSObject>(context->extension()); | 1294 context_ext = Handle<JSObject>(JSObject::cast(context->extension())); |
| 1289 } else { | 1295 } else { |
| 1290 // The function context's extension context does not exists - allocate | 1296 // The function context's extension context does not exists - allocate |
| 1291 // it. | 1297 // it. |
| 1292 context_ext = isolate->factory()->NewJSObject( | 1298 context_ext = isolate->factory()->NewJSObject( |
| 1293 isolate->context_extension_function()); | 1299 isolate->context_extension_function()); |
| 1294 // And store it in the extension slot. | 1300 // And store it in the extension slot. |
| 1295 context->set_extension(*context_ext); | 1301 context->set_extension(*context_ext); |
| 1296 } | 1302 } |
| 1297 ASSERT(*context_ext != NULL); | 1303 ASSERT(*context_ext != NULL); |
| 1298 | 1304 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1332 // args[2] == value (optional) | 1338 // args[2] == value (optional) |
| 1333 | 1339 |
| 1334 // Determine if we need to assign to the variable if it already | 1340 // Determine if we need to assign to the variable if it already |
| 1335 // exists (based on the number of arguments). | 1341 // exists (based on the number of arguments). |
| 1336 RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); | 1342 RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); |
| 1337 bool assign = args.length() == 3; | 1343 bool assign = args.length() == 3; |
| 1338 | 1344 |
| 1339 CONVERT_ARG_CHECKED(String, name, 0); | 1345 CONVERT_ARG_CHECKED(String, name, 0); |
| 1340 GlobalObject* global = isolate->context()->global(); | 1346 GlobalObject* global = isolate->context()->global(); |
| 1341 RUNTIME_ASSERT(args[1]->IsSmi()); | 1347 RUNTIME_ASSERT(args[1]->IsSmi()); |
| 1342 StrictModeFlag strict_mode = | 1348 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(1)); |
| 1343 static_cast<StrictModeFlag>(Smi::cast(args[1])->value()); | |
| 1344 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); | 1349 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); |
| 1345 | 1350 |
| 1346 // According to ECMA-262, section 12.2, page 62, the property must | 1351 // According to ECMA-262, section 12.2, page 62, the property must |
| 1347 // not be deletable. | 1352 // not be deletable. |
| 1348 PropertyAttributes attributes = DONT_DELETE; | 1353 PropertyAttributes attributes = DONT_DELETE; |
| 1349 | 1354 |
| 1350 // Lookup the property locally in the global object. If it isn't | 1355 // Lookup the property locally in the global object. If it isn't |
| 1351 // there, there is a property with this name in the prototype chain. | 1356 // there, there is a property with this name in the prototype chain. |
| 1352 // We follow Safari and Firefox behavior and only set the property | 1357 // We follow Safari and Firefox behavior and only set the property |
| 1353 // locally if there is an explicit initialization value that we have | 1358 // locally if there is an explicit initialization value that we have |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1512 | 1517 |
| 1513 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { | 1518 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { |
| 1514 HandleScope scope(isolate); | 1519 HandleScope scope(isolate); |
| 1515 ASSERT(args.length() == 3); | 1520 ASSERT(args.length() == 3); |
| 1516 | 1521 |
| 1517 Handle<Object> value(args[0], isolate); | 1522 Handle<Object> value(args[0], isolate); |
| 1518 ASSERT(!value->IsTheHole()); | 1523 ASSERT(!value->IsTheHole()); |
| 1519 CONVERT_ARG_CHECKED(Context, context, 1); | 1524 CONVERT_ARG_CHECKED(Context, context, 1); |
| 1520 Handle<String> name(String::cast(args[2])); | 1525 Handle<String> name(String::cast(args[2])); |
| 1521 | 1526 |
| 1522 // Initializations are always done in the function context. | 1527 // Initializations are always done in a function or global context. |
| 1523 context = Handle<Context>(context->fcontext()); | 1528 context = Handle<Context>(context->declaration_context()); |
| 1524 | 1529 |
| 1525 int index; | 1530 int index; |
| 1526 PropertyAttributes attributes; | 1531 PropertyAttributes attributes; |
| 1527 ContextLookupFlags flags = FOLLOW_CHAINS; | 1532 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 1528 Handle<Object> holder = | 1533 Handle<Object> holder = |
| 1529 context->Lookup(name, flags, &index, &attributes); | 1534 context->Lookup(name, flags, &index, &attributes); |
| 1530 | 1535 |
| 1531 // In most situations, the property introduced by the const | 1536 // In most situations, the property introduced by the const |
| 1532 // declaration should be present in the context extension object. | 1537 // declaration should be present in the context extension object. |
| 1533 // However, because declaration and initialization are separate, the | 1538 // However, because declaration and initialization are separate, the |
| 1534 // property might have been deleted (if it was introduced by eval) | 1539 // property might have been deleted (if it was introduced by eval) |
| 1535 // before we reach the initialization point. | 1540 // before we reach the initialization point. |
| 1536 // | 1541 // |
| 1537 // Example: | 1542 // Example: |
| 1538 // | 1543 // |
| 1539 // function f() { eval("delete x; const x;"); } | 1544 // function f() { eval("delete x; const x;"); } |
| 1540 // | 1545 // |
| 1541 // In that case, the initialization behaves like a normal assignment | 1546 // In that case, the initialization behaves like a normal assignment |
| 1542 // to property 'x'. | 1547 // to property 'x'. |
| 1543 if (index >= 0) { | 1548 if (index >= 0) { |
| 1544 // Property was found in a context. | |
| 1545 if (holder->IsContext()) { | 1549 if (holder->IsContext()) { |
| 1546 // The holder cannot be the function context. If it is, there | 1550 // Property was found in a context. Perform the assignment if we |
| 1547 // should have been a const redeclaration error when declaring | 1551 // found some non-constant or an uninitialized constant. |
| 1548 // the const property. | 1552 Handle<Context> context = Handle<Context>::cast(holder); |
| 1549 ASSERT(!holder.is_identical_to(context)); | 1553 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { |
| 1550 if ((attributes & READ_ONLY) == 0) { | 1554 context->set(index, *value); |
| 1551 Handle<Context>::cast(holder)->set(index, *value); | |
| 1552 } | 1555 } |
| 1553 } else { | 1556 } else { |
| 1554 // The holder is an arguments object. | 1557 // The holder is an arguments object. |
| 1555 ASSERT((attributes & READ_ONLY) == 0); | 1558 ASSERT((attributes & READ_ONLY) == 0); |
| 1556 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | 1559 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); |
| 1557 RETURN_IF_EMPTY_HANDLE( | 1560 RETURN_IF_EMPTY_HANDLE( |
| 1558 isolate, | 1561 isolate, |
| 1559 SetElement(arguments, index, value, kNonStrictMode)); | 1562 SetElement(arguments, index, value, kNonStrictMode)); |
| 1560 } | 1563 } |
| 1561 return *value; | 1564 return *value; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1615 | 1618 |
| 1616 return *value; | 1619 return *value; |
| 1617 } | 1620 } |
| 1618 | 1621 |
| 1619 | 1622 |
| 1620 RUNTIME_FUNCTION(MaybeObject*, | 1623 RUNTIME_FUNCTION(MaybeObject*, |
| 1621 Runtime_OptimizeObjectForAddingMultipleProperties) { | 1624 Runtime_OptimizeObjectForAddingMultipleProperties) { |
| 1622 HandleScope scope(isolate); | 1625 HandleScope scope(isolate); |
| 1623 ASSERT(args.length() == 2); | 1626 ASSERT(args.length() == 2); |
| 1624 CONVERT_ARG_CHECKED(JSObject, object, 0); | 1627 CONVERT_ARG_CHECKED(JSObject, object, 0); |
| 1625 CONVERT_SMI_CHECKED(properties, args[1]); | 1628 CONVERT_SMI_ARG_CHECKED(properties, 1); |
| 1626 if (object->HasFastProperties()) { | 1629 if (object->HasFastProperties()) { |
| 1627 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); | 1630 NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); |
| 1628 } | 1631 } |
| 1629 return *object; | 1632 return *object; |
| 1630 } | 1633 } |
| 1631 | 1634 |
| 1632 | 1635 |
| 1633 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { | 1636 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { |
| 1634 HandleScope scope(isolate); | 1637 HandleScope scope(isolate); |
| 1635 ASSERT(args.length() == 4); | 1638 ASSERT(args.length() == 4); |
| 1636 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); | 1639 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); |
| 1637 CONVERT_ARG_CHECKED(String, subject, 1); | 1640 CONVERT_ARG_CHECKED(String, subject, 1); |
| 1638 // Due to the way the JS calls are constructed this must be less than the | 1641 // Due to the way the JS calls are constructed this must be less than the |
| 1639 // length of a string, i.e. it is always a Smi. We check anyway for security. | 1642 // length of a string, i.e. it is always a Smi. We check anyway for security. |
| 1640 CONVERT_SMI_CHECKED(index, args[2]); | 1643 CONVERT_SMI_ARG_CHECKED(index, 2); |
| 1641 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); | 1644 CONVERT_ARG_CHECKED(JSArray, last_match_info, 3); |
| 1642 RUNTIME_ASSERT(last_match_info->HasFastElements()); | 1645 RUNTIME_ASSERT(last_match_info->HasFastElements()); |
| 1643 RUNTIME_ASSERT(index >= 0); | 1646 RUNTIME_ASSERT(index >= 0); |
| 1644 RUNTIME_ASSERT(index <= subject->length()); | 1647 RUNTIME_ASSERT(index <= subject->length()); |
| 1645 isolate->counters()->regexp_entry_runtime()->Increment(); | 1648 isolate->counters()->regexp_entry_runtime()->Increment(); |
| 1646 Handle<Object> result = RegExpImpl::Exec(regexp, | 1649 Handle<Object> result = RegExpImpl::Exec(regexp, |
| 1647 subject, | 1650 subject, |
| 1648 index, | 1651 index, |
| 1649 last_match_info); | 1652 last_match_info); |
| 1650 if (result.is_null()) return Failure::Exception(); | 1653 if (result.is_null()) return Failure::Exception(); |
| 1651 return *result; | 1654 return *result; |
| 1652 } | 1655 } |
| 1653 | 1656 |
| 1654 | 1657 |
| 1655 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) { | 1658 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) { |
| 1656 ASSERT(args.length() == 3); | 1659 ASSERT(args.length() == 3); |
| 1657 CONVERT_SMI_CHECKED(elements_count, args[0]); | 1660 CONVERT_SMI_ARG_CHECKED(elements_count, 0); |
| 1658 if (elements_count > JSArray::kMaxFastElementsLength) { | 1661 if (elements_count > JSArray::kMaxFastElementsLength) { |
| 1659 return isolate->ThrowIllegalOperation(); | 1662 return isolate->ThrowIllegalOperation(); |
| 1660 } | 1663 } |
| 1661 Object* new_object; | 1664 Object* new_object; |
| 1662 { MaybeObject* maybe_new_object = | 1665 { MaybeObject* maybe_new_object = |
| 1663 isolate->heap()->AllocateFixedArrayWithHoles(elements_count); | 1666 isolate->heap()->AllocateFixedArrayWithHoles(elements_count); |
| 1664 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; | 1667 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; |
| 1665 } | 1668 } |
| 1666 FixedArray* elements = FixedArray::cast(new_object); | 1669 FixedArray* elements = FixedArray::cast(new_object); |
| 1667 { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw( | 1670 { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw( |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1802 Context* global_context = | 1805 Context* global_context = |
| 1803 isolate->context()->global()->global_context(); | 1806 isolate->context()->global()->global_context(); |
| 1804 return global_context->global()->global_receiver(); | 1807 return global_context->global()->global_receiver(); |
| 1805 } | 1808 } |
| 1806 | 1809 |
| 1807 | 1810 |
| 1808 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) { | 1811 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) { |
| 1809 HandleScope scope(isolate); | 1812 HandleScope scope(isolate); |
| 1810 ASSERT(args.length() == 4); | 1813 ASSERT(args.length() == 4); |
| 1811 CONVERT_ARG_CHECKED(FixedArray, literals, 0); | 1814 CONVERT_ARG_CHECKED(FixedArray, literals, 0); |
| 1812 int index = Smi::cast(args[1])->value(); | 1815 int index = args.smi_at(1); |
| 1813 Handle<String> pattern = args.at<String>(2); | 1816 Handle<String> pattern = args.at<String>(2); |
| 1814 Handle<String> flags = args.at<String>(3); | 1817 Handle<String> flags = args.at<String>(3); |
| 1815 | 1818 |
| 1816 // Get the RegExp function from the context in the literals array. | 1819 // Get the RegExp function from the context in the literals array. |
| 1817 // This is the RegExp function from the context in which the | 1820 // This is the RegExp function from the context in which the |
| 1818 // function was created. We do not use the RegExp function from the | 1821 // function was created. We do not use the RegExp function from the |
| 1819 // current global context because this might be the RegExp function | 1822 // current global context because this might be the RegExp function |
| 1820 // from another context which we should not have access to. | 1823 // from another context which we should not have access to. |
| 1821 Handle<JSFunction> constructor = | 1824 Handle<JSFunction> constructor = |
| 1822 Handle<JSFunction>( | 1825 Handle<JSFunction>( |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1848 NoHandleAllocation ha; | 1851 NoHandleAllocation ha; |
| 1849 ASSERT(args.length() == 2); | 1852 ASSERT(args.length() == 2); |
| 1850 | 1853 |
| 1851 CONVERT_CHECKED(JSFunction, f, args[0]); | 1854 CONVERT_CHECKED(JSFunction, f, args[0]); |
| 1852 CONVERT_CHECKED(String, name, args[1]); | 1855 CONVERT_CHECKED(String, name, args[1]); |
| 1853 f->shared()->set_name(name); | 1856 f->shared()->set_name(name); |
| 1854 return isolate->heap()->undefined_value(); | 1857 return isolate->heap()->undefined_value(); |
| 1855 } | 1858 } |
| 1856 | 1859 |
| 1857 | 1860 |
| 1861 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetBound) { |
| 1862 HandleScope scope(isolate); |
| 1863 ASSERT(args.length() == 1); |
| 1864 |
| 1865 CONVERT_CHECKED(JSFunction, fun, args[0]); |
| 1866 fun->shared()->set_bound(true); |
| 1867 return isolate->heap()->undefined_value(); |
| 1868 } |
| 1869 |
| 1858 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { | 1870 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { |
| 1859 NoHandleAllocation ha; | 1871 NoHandleAllocation ha; |
| 1860 ASSERT(args.length() == 1); | 1872 ASSERT(args.length() == 1); |
| 1861 | 1873 |
| 1862 CONVERT_CHECKED(JSFunction, f, args[0]); | 1874 CONVERT_CHECKED(JSFunction, f, args[0]); |
| 1863 Object* obj = f->RemovePrototype(); | 1875 Object* obj = f->RemovePrototype(); |
| 1864 if (obj->IsFailure()) return obj; | 1876 if (obj->IsFailure()) return obj; |
| 1865 | 1877 |
| 1866 return isolate->heap()->undefined_value(); | 1878 return isolate->heap()->undefined_value(); |
| 1867 } | 1879 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 | 2040 |
| 2029 target->set_context(*context); | 2041 target->set_context(*context); |
| 2030 return *target; | 2042 return *target; |
| 2031 } | 2043 } |
| 2032 | 2044 |
| 2033 | 2045 |
| 2034 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) { | 2046 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) { |
| 2035 HandleScope scope(isolate); | 2047 HandleScope scope(isolate); |
| 2036 ASSERT(args.length() == 2); | 2048 ASSERT(args.length() == 2); |
| 2037 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 2049 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 2038 CONVERT_SMI_CHECKED(num, args[1]); | 2050 CONVERT_SMI_ARG_CHECKED(num, 1); |
| 2039 RUNTIME_ASSERT(num >= 0); | 2051 RUNTIME_ASSERT(num >= 0); |
| 2040 SetExpectedNofProperties(function, num); | 2052 SetExpectedNofProperties(function, num); |
| 2041 return isolate->heap()->undefined_value(); | 2053 return isolate->heap()->undefined_value(); |
| 2042 } | 2054 } |
| 2043 | 2055 |
| 2044 | 2056 |
| 2045 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, | 2057 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, |
| 2046 Object* char_code) { | 2058 Object* char_code) { |
| 2047 uint32_t code; | 2059 uint32_t code; |
| 2048 if (char_code->ToArrayIndex(&code)) { | 2060 if (char_code->ToArrayIndex(&code)) { |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2252 } | 2264 } |
| 2253 | 2265 |
| 2254 | 2266 |
| 2255 Handle<String> ToString() { | 2267 Handle<String> ToString() { |
| 2256 if (array_builder_.length() == 0) { | 2268 if (array_builder_.length() == 0) { |
| 2257 return heap_->isolate()->factory()->empty_string(); | 2269 return heap_->isolate()->factory()->empty_string(); |
| 2258 } | 2270 } |
| 2259 | 2271 |
| 2260 Handle<String> joined_string; | 2272 Handle<String> joined_string; |
| 2261 if (is_ascii_) { | 2273 if (is_ascii_) { |
| 2262 joined_string = NewRawAsciiString(character_count_); | 2274 Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_); |
| 2263 AssertNoAllocation no_alloc; | 2275 AssertNoAllocation no_alloc; |
| 2264 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string); | |
| 2265 char* char_buffer = seq->GetChars(); | 2276 char* char_buffer = seq->GetChars(); |
| 2266 StringBuilderConcatHelper(*subject_, | 2277 StringBuilderConcatHelper(*subject_, |
| 2267 char_buffer, | 2278 char_buffer, |
| 2268 *array_builder_.array(), | 2279 *array_builder_.array(), |
| 2269 array_builder_.length()); | 2280 array_builder_.length()); |
| 2281 joined_string = Handle<String>::cast(seq); |
| 2270 } else { | 2282 } else { |
| 2271 // Non-ASCII. | 2283 // Non-ASCII. |
| 2272 joined_string = NewRawTwoByteString(character_count_); | 2284 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); |
| 2273 AssertNoAllocation no_alloc; | 2285 AssertNoAllocation no_alloc; |
| 2274 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string); | |
| 2275 uc16* char_buffer = seq->GetChars(); | 2286 uc16* char_buffer = seq->GetChars(); |
| 2276 StringBuilderConcatHelper(*subject_, | 2287 StringBuilderConcatHelper(*subject_, |
| 2277 char_buffer, | 2288 char_buffer, |
| 2278 *array_builder_.array(), | 2289 *array_builder_.array(), |
| 2279 array_builder_.length()); | 2290 array_builder_.length()); |
| 2291 joined_string = Handle<String>::cast(seq); |
| 2280 } | 2292 } |
| 2281 return joined_string; | 2293 return joined_string; |
| 2282 } | 2294 } |
| 2283 | 2295 |
| 2284 | 2296 |
| 2285 void IncrementCharacterCount(int by) { | 2297 void IncrementCharacterCount(int by) { |
| 2286 if (character_count_ > String::kMaxLength - by) { | 2298 if (character_count_ > String::kMaxLength - by) { |
| 2287 V8::FatalProcessOutOfMemory("String.replace result too large."); | 2299 V8::FatalProcessOutOfMemory("String.replace result too large."); |
| 2288 } | 2300 } |
| 2289 character_count_ += by; | 2301 character_count_ += by; |
| 2290 } | 2302 } |
| 2291 | 2303 |
| 2292 Handle<JSArray> GetParts() { | 2304 Handle<JSArray> GetParts() { |
| 2293 return array_builder_.ToJSArray(); | 2305 return array_builder_.ToJSArray(); |
| 2294 } | 2306 } |
| 2295 | 2307 |
| 2296 private: | 2308 private: |
| 2297 Handle<String> NewRawAsciiString(int size) { | 2309 Handle<SeqAsciiString> NewRawAsciiString(int length) { |
| 2298 CALL_HEAP_FUNCTION(heap_->isolate(), | 2310 return heap_->isolate()->factory()->NewRawAsciiString(length); |
| 2299 heap_->AllocateRawAsciiString(size), String); | |
| 2300 } | 2311 } |
| 2301 | 2312 |
| 2302 | 2313 |
| 2303 Handle<String> NewRawTwoByteString(int size) { | 2314 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { |
| 2304 CALL_HEAP_FUNCTION(heap_->isolate(), | 2315 return heap_->isolate()->factory()->NewRawTwoByteString(length); |
| 2305 heap_->AllocateRawTwoByteString(size), String); | |
| 2306 } | 2316 } |
| 2307 | 2317 |
| 2308 | 2318 |
| 2309 void AddElement(Object* element) { | 2319 void AddElement(Object* element) { |
| 2310 ASSERT(element->IsSmi() || element->IsString()); | 2320 ASSERT(element->IsSmi() || element->IsString()); |
| 2311 ASSERT(array_builder_.capacity() > array_builder_.length()); | 2321 ASSERT(array_builder_.capacity() > array_builder_.length()); |
| 2312 array_builder_.Add(element); | 2322 array_builder_.Add(element); |
| 2313 } | 2323 } |
| 2314 | 2324 |
| 2315 Heap* heap_; | 2325 Heap* heap_; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2331 | 2341 |
| 2332 void Apply(ReplacementStringBuilder* builder, | 2342 void Apply(ReplacementStringBuilder* builder, |
| 2333 int match_from, | 2343 int match_from, |
| 2334 int match_to, | 2344 int match_to, |
| 2335 Handle<JSArray> last_match_info); | 2345 Handle<JSArray> last_match_info); |
| 2336 | 2346 |
| 2337 // Number of distinct parts of the replacement pattern. | 2347 // Number of distinct parts of the replacement pattern. |
| 2338 int parts() { | 2348 int parts() { |
| 2339 return parts_.length(); | 2349 return parts_.length(); |
| 2340 } | 2350 } |
| 2351 |
| 2341 private: | 2352 private: |
| 2342 enum PartType { | 2353 enum PartType { |
| 2343 SUBJECT_PREFIX = 1, | 2354 SUBJECT_PREFIX = 1, |
| 2344 SUBJECT_SUFFIX, | 2355 SUBJECT_SUFFIX, |
| 2345 SUBJECT_CAPTURE, | 2356 SUBJECT_CAPTURE, |
| 2346 REPLACEMENT_SUBSTRING, | 2357 REPLACEMENT_SUBSTRING, |
| 2347 REPLACEMENT_STRING, | 2358 REPLACEMENT_STRING, |
| 2348 | 2359 |
| 2349 NUMBER_OF_PART_TYPES | 2360 NUMBER_OF_PART_TYPES |
| 2350 }; | 2361 }; |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2607 if (match.is_null()) { | 2618 if (match.is_null()) { |
| 2608 return Failure::Exception(); | 2619 return Failure::Exception(); |
| 2609 } | 2620 } |
| 2610 if (match->IsNull()) { | 2621 if (match->IsNull()) { |
| 2611 return *subject_handle; | 2622 return *subject_handle; |
| 2612 } | 2623 } |
| 2613 | 2624 |
| 2614 int capture_count = regexp_handle->CaptureCount(); | 2625 int capture_count = regexp_handle->CaptureCount(); |
| 2615 | 2626 |
| 2616 // CompiledReplacement uses zone allocation. | 2627 // CompiledReplacement uses zone allocation. |
| 2617 CompilationZoneScope zone(isolate, DELETE_ON_EXIT); | 2628 ZoneScope zone(isolate, DELETE_ON_EXIT); |
| 2618 CompiledReplacement compiled_replacement; | 2629 CompiledReplacement compiled_replacement; |
| 2619 compiled_replacement.Compile(replacement_handle, | 2630 compiled_replacement.Compile(replacement_handle, |
| 2620 capture_count, | 2631 capture_count, |
| 2621 length); | 2632 length); |
| 2622 | 2633 |
| 2623 bool is_global = regexp_handle->GetFlags().is_global(); | 2634 bool is_global = regexp_handle->GetFlags().is_global(); |
| 2624 | 2635 |
| 2625 // Guessing the number of parts that the final result string is built | 2636 // Guessing the number of parts that the final result string is built |
| 2626 // from. Global regexps can match any number of times, so we guess | 2637 // from. Global regexps can match any number of times, so we guess |
| 2627 // conservatively. | 2638 // conservatively. |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3084 | 3095 |
| 3085 return Smi::FromInt(str1_length - str2_length); | 3096 return Smi::FromInt(str1_length - str2_length); |
| 3086 } | 3097 } |
| 3087 | 3098 |
| 3088 | 3099 |
| 3089 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) { | 3100 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) { |
| 3090 NoHandleAllocation ha; | 3101 NoHandleAllocation ha; |
| 3091 ASSERT(args.length() == 3); | 3102 ASSERT(args.length() == 3); |
| 3092 | 3103 |
| 3093 CONVERT_CHECKED(String, value, args[0]); | 3104 CONVERT_CHECKED(String, value, args[0]); |
| 3094 Object* from = args[1]; | |
| 3095 Object* to = args[2]; | |
| 3096 int start, end; | 3105 int start, end; |
| 3097 // We have a fast integer-only case here to avoid a conversion to double in | 3106 // We have a fast integer-only case here to avoid a conversion to double in |
| 3098 // the common case where from and to are Smis. | 3107 // the common case where from and to are Smis. |
| 3099 if (from->IsSmi() && to->IsSmi()) { | 3108 if (args[1]->IsSmi() && args[2]->IsSmi()) { |
| 3100 start = Smi::cast(from)->value(); | 3109 CONVERT_SMI_ARG_CHECKED(from_number, 1); |
| 3101 end = Smi::cast(to)->value(); | 3110 CONVERT_SMI_ARG_CHECKED(to_number, 2); |
| 3111 start = from_number; |
| 3112 end = to_number; |
| 3102 } else { | 3113 } else { |
| 3103 CONVERT_DOUBLE_CHECKED(from_number, from); | 3114 CONVERT_DOUBLE_ARG_CHECKED(from_number, 1); |
| 3104 CONVERT_DOUBLE_CHECKED(to_number, to); | 3115 CONVERT_DOUBLE_ARG_CHECKED(to_number, 2); |
| 3105 start = FastD2I(from_number); | 3116 start = FastD2I(from_number); |
| 3106 end = FastD2I(to_number); | 3117 end = FastD2I(to_number); |
| 3107 } | 3118 } |
| 3108 RUNTIME_ASSERT(end >= start); | 3119 RUNTIME_ASSERT(end >= start); |
| 3109 RUNTIME_ASSERT(start >= 0); | 3120 RUNTIME_ASSERT(start >= 0); |
| 3110 RUNTIME_ASSERT(end <= value->length()); | 3121 RUNTIME_ASSERT(end <= value->length()); |
| 3111 isolate->counters()->sub_string_runtime()->Increment(); | 3122 isolate->counters()->sub_string_runtime()->Increment(); |
| 3112 return value->SubString(start, end); | 3123 return value->SubString(start, end); |
| 3113 } | 3124 } |
| 3114 | 3125 |
| 3115 | 3126 |
| 3116 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) { | 3127 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) { |
| 3117 ASSERT_EQ(3, args.length()); | 3128 ASSERT_EQ(3, args.length()); |
| 3118 | 3129 |
| 3119 CONVERT_ARG_CHECKED(String, subject, 0); | 3130 CONVERT_ARG_CHECKED(String, subject, 0); |
| 3120 CONVERT_ARG_CHECKED(JSRegExp, regexp, 1); | 3131 CONVERT_ARG_CHECKED(JSRegExp, regexp, 1); |
| 3121 CONVERT_ARG_CHECKED(JSArray, regexp_info, 2); | 3132 CONVERT_ARG_CHECKED(JSArray, regexp_info, 2); |
| 3122 HandleScope handles; | 3133 HandleScope handles; |
| 3123 | 3134 |
| 3124 Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info); | 3135 Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info); |
| 3125 | 3136 |
| 3126 if (match.is_null()) { | 3137 if (match.is_null()) { |
| 3127 return Failure::Exception(); | 3138 return Failure::Exception(); |
| 3128 } | 3139 } |
| 3129 if (match->IsNull()) { | 3140 if (match->IsNull()) { |
| 3130 return isolate->heap()->null_value(); | 3141 return isolate->heap()->null_value(); |
| 3131 } | 3142 } |
| 3132 int length = subject->length(); | 3143 int length = subject->length(); |
| 3133 | 3144 |
| 3134 CompilationZoneScope zone_space(isolate, DELETE_ON_EXIT); | 3145 ZoneScope zone_space(isolate, DELETE_ON_EXIT); |
| 3135 ZoneList<int> offsets(8); | 3146 ZoneList<int> offsets(8); |
| 3147 int start; |
| 3148 int end; |
| 3136 do { | 3149 do { |
| 3137 int start; | |
| 3138 int end; | |
| 3139 { | 3150 { |
| 3140 AssertNoAllocation no_alloc; | 3151 AssertNoAllocation no_alloc; |
| 3141 FixedArray* elements = FixedArray::cast(regexp_info->elements()); | 3152 FixedArray* elements = FixedArray::cast(regexp_info->elements()); |
| 3142 start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value(); | 3153 start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value(); |
| 3143 end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value(); | 3154 end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value(); |
| 3144 } | 3155 } |
| 3145 offsets.Add(start); | 3156 offsets.Add(start); |
| 3146 offsets.Add(end); | 3157 offsets.Add(end); |
| 3147 int index = start < end ? end : end + 1; | 3158 if (start == end) if (++end > length) break; |
| 3148 if (index > length) break; | 3159 match = RegExpImpl::Exec(regexp, subject, end, regexp_info); |
| 3149 match = RegExpImpl::Exec(regexp, subject, index, regexp_info); | |
| 3150 if (match.is_null()) { | 3160 if (match.is_null()) { |
| 3151 return Failure::Exception(); | 3161 return Failure::Exception(); |
| 3152 } | 3162 } |
| 3153 } while (!match->IsNull()); | 3163 } while (!match->IsNull()); |
| 3154 int matches = offsets.length() / 2; | 3164 int matches = offsets.length() / 2; |
| 3155 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches); | 3165 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches); |
| 3156 for (int i = 0; i < matches ; i++) { | 3166 Handle<String> substring = isolate->factory()-> |
| 3167 NewSubString(subject, offsets.at(0), offsets.at(1)); |
| 3168 elements->set(0, *substring); |
| 3169 for (int i = 1; i < matches ; i++) { |
| 3157 int from = offsets.at(i * 2); | 3170 int from = offsets.at(i * 2); |
| 3158 int to = offsets.at(i * 2 + 1); | 3171 int to = offsets.at(i * 2 + 1); |
| 3159 Handle<String> match = isolate->factory()->NewSubString(subject, from, to); | 3172 Handle<String> substring = isolate->factory()-> |
| 3160 elements->set(i, *match); | 3173 NewProperSubString(subject, from, to); |
| 3174 elements->set(i, *substring); |
| 3161 } | 3175 } |
| 3162 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements); | 3176 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements); |
| 3163 result->set_length(Smi::FromInt(matches)); | 3177 result->set_length(Smi::FromInt(matches)); |
| 3164 return *result; | 3178 return *result; |
| 3165 } | 3179 } |
| 3166 | 3180 |
| 3167 | 3181 |
| 3168 // Two smis before and after the match, for very long strings. | 3182 // Two smis before and after the match, for very long strings. |
| 3169 const int kMaxBuilderEntriesPerRegExpMatch = 5; | 3183 const int kMaxBuilderEntriesPerRegExpMatch = 5; |
| 3170 | 3184 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3300 ASSERT(subject->IsFlat()); | 3314 ASSERT(subject->IsFlat()); |
| 3301 int match_start = -1; | 3315 int match_start = -1; |
| 3302 int match_end = 0; | 3316 int match_end = 0; |
| 3303 int pos = 0; | 3317 int pos = 0; |
| 3304 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); | 3318 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
| 3305 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; | 3319 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; |
| 3306 | 3320 |
| 3307 OffsetsVector registers(required_registers); | 3321 OffsetsVector registers(required_registers); |
| 3308 Vector<int32_t> register_vector(registers.vector(), registers.length()); | 3322 Vector<int32_t> register_vector(registers.vector(), registers.length()); |
| 3309 int subject_length = subject->length(); | 3323 int subject_length = subject->length(); |
| 3324 bool first = true; |
| 3310 | 3325 |
| 3311 for (;;) { // Break on failure, return on exception. | 3326 for (;;) { // Break on failure, return on exception. |
| 3312 RegExpImpl::IrregexpResult result = | 3327 RegExpImpl::IrregexpResult result = |
| 3313 RegExpImpl::IrregexpExecOnce(regexp, | 3328 RegExpImpl::IrregexpExecOnce(regexp, |
| 3314 subject, | 3329 subject, |
| 3315 pos, | 3330 pos, |
| 3316 register_vector); | 3331 register_vector); |
| 3317 if (result == RegExpImpl::RE_SUCCESS) { | 3332 if (result == RegExpImpl::RE_SUCCESS) { |
| 3318 match_start = register_vector[0]; | 3333 match_start = register_vector[0]; |
| 3319 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3334 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| 3320 if (match_end < match_start) { | 3335 if (match_end < match_start) { |
| 3321 ReplacementStringBuilder::AddSubjectSlice(builder, | 3336 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3322 match_end, | 3337 match_end, |
| 3323 match_start); | 3338 match_start); |
| 3324 } | 3339 } |
| 3325 match_end = register_vector[1]; | 3340 match_end = register_vector[1]; |
| 3326 HandleScope loop_scope(isolate); | 3341 HandleScope loop_scope(isolate); |
| 3327 builder->Add(*isolate->factory()->NewSubString(subject, | 3342 if (!first) { |
| 3328 match_start, | 3343 builder->Add(*isolate->factory()->NewProperSubString(subject, |
| 3329 match_end)); | 3344 match_start, |
| 3345 match_end)); |
| 3346 } else { |
| 3347 builder->Add(*isolate->factory()->NewSubString(subject, |
| 3348 match_start, |
| 3349 match_end)); |
| 3350 } |
| 3330 if (match_start != match_end) { | 3351 if (match_start != match_end) { |
| 3331 pos = match_end; | 3352 pos = match_end; |
| 3332 } else { | 3353 } else { |
| 3333 pos = match_end + 1; | 3354 pos = match_end + 1; |
| 3334 if (pos > subject_length) break; | 3355 if (pos > subject_length) break; |
| 3335 } | 3356 } |
| 3336 } else if (result == RegExpImpl::RE_FAILURE) { | 3357 } else if (result == RegExpImpl::RE_FAILURE) { |
| 3337 break; | 3358 break; |
| 3338 } else { | 3359 } else { |
| 3339 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); | 3360 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| 3340 return result; | 3361 return result; |
| 3341 } | 3362 } |
| 3363 first = false; |
| 3342 } | 3364 } |
| 3343 | 3365 |
| 3344 if (match_start >= 0) { | 3366 if (match_start >= 0) { |
| 3345 if (match_end < subject_length) { | 3367 if (match_end < subject_length) { |
| 3346 ReplacementStringBuilder::AddSubjectSlice(builder, | 3368 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3347 match_end, | 3369 match_end, |
| 3348 subject_length); | 3370 subject_length); |
| 3349 } | 3371 } |
| 3350 SetLastMatchInfoNoCaptures(subject, | 3372 SetLastMatchInfoNoCaptures(subject, |
| 3351 last_match_array, | 3373 last_match_array, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3383 | 3405 |
| 3384 // Position to search from. | 3406 // Position to search from. |
| 3385 int pos = 0; | 3407 int pos = 0; |
| 3386 // End of previous match. Differs from pos if match was empty. | 3408 // End of previous match. Differs from pos if match was empty. |
| 3387 int match_end = 0; | 3409 int match_end = 0; |
| 3388 if (result == RegExpImpl::RE_SUCCESS) { | 3410 if (result == RegExpImpl::RE_SUCCESS) { |
| 3389 // Need to keep a copy of the previous match for creating last_match_info | 3411 // Need to keep a copy of the previous match for creating last_match_info |
| 3390 // at the end, so we have two vectors that we swap between. | 3412 // at the end, so we have two vectors that we swap between. |
| 3391 OffsetsVector registers2(required_registers); | 3413 OffsetsVector registers2(required_registers); |
| 3392 Vector<int> prev_register_vector(registers2.vector(), registers2.length()); | 3414 Vector<int> prev_register_vector(registers2.vector(), registers2.length()); |
| 3393 | 3415 bool first = true; |
| 3394 do { | 3416 do { |
| 3395 int match_start = register_vector[0]; | 3417 int match_start = register_vector[0]; |
| 3396 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3418 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| 3397 if (match_end < match_start) { | 3419 if (match_end < match_start) { |
| 3398 ReplacementStringBuilder::AddSubjectSlice(builder, | 3420 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3399 match_end, | 3421 match_end, |
| 3400 match_start); | 3422 match_start); |
| 3401 } | 3423 } |
| 3402 match_end = register_vector[1]; | 3424 match_end = register_vector[1]; |
| 3403 | 3425 |
| 3404 { | 3426 { |
| 3405 // Avoid accumulating new handles inside loop. | 3427 // Avoid accumulating new handles inside loop. |
| 3406 HandleScope temp_scope(isolate); | 3428 HandleScope temp_scope(isolate); |
| 3407 // Arguments array to replace function is match, captures, index and | 3429 // Arguments array to replace function is match, captures, index and |
| 3408 // subject, i.e., 3 + capture count in total. | 3430 // subject, i.e., 3 + capture count in total. |
| 3409 Handle<FixedArray> elements = | 3431 Handle<FixedArray> elements = |
| 3410 isolate->factory()->NewFixedArray(3 + capture_count); | 3432 isolate->factory()->NewFixedArray(3 + capture_count); |
| 3411 Handle<String> match = isolate->factory()->NewSubString(subject, | 3433 Handle<String> match; |
| 3412 match_start, | 3434 if (!first) { |
| 3413 match_end); | 3435 match = isolate->factory()->NewProperSubString(subject, |
| 3436 match_start, |
| 3437 match_end); |
| 3438 } else { |
| 3439 match = isolate->factory()->NewSubString(subject, |
| 3440 match_start, |
| 3441 match_end); |
| 3442 } |
| 3414 elements->set(0, *match); | 3443 elements->set(0, *match); |
| 3415 for (int i = 1; i <= capture_count; i++) { | 3444 for (int i = 1; i <= capture_count; i++) { |
| 3416 int start = register_vector[i * 2]; | 3445 int start = register_vector[i * 2]; |
| 3417 if (start >= 0) { | 3446 if (start >= 0) { |
| 3418 int end = register_vector[i * 2 + 1]; | 3447 int end = register_vector[i * 2 + 1]; |
| 3419 ASSERT(start <= end); | 3448 ASSERT(start <= end); |
| 3420 Handle<String> substring = isolate->factory()->NewSubString(subject, | 3449 Handle<String> substring; |
| 3421 start, | 3450 if (!first) { |
| 3422 end); | 3451 substring = isolate->factory()->NewProperSubString(subject, |
| 3452 start, |
| 3453 end); |
| 3454 } else { |
| 3455 substring = isolate->factory()->NewSubString(subject, start, end); |
| 3456 } |
| 3423 elements->set(i, *substring); | 3457 elements->set(i, *substring); |
| 3424 } else { | 3458 } else { |
| 3425 ASSERT(register_vector[i * 2 + 1] < 0); | 3459 ASSERT(register_vector[i * 2 + 1] < 0); |
| 3426 elements->set(i, isolate->heap()->undefined_value()); | 3460 elements->set(i, isolate->heap()->undefined_value()); |
| 3427 } | 3461 } |
| 3428 } | 3462 } |
| 3429 elements->set(capture_count + 1, Smi::FromInt(match_start)); | 3463 elements->set(capture_count + 1, Smi::FromInt(match_start)); |
| 3430 elements->set(capture_count + 2, *subject); | 3464 elements->set(capture_count + 2, *subject); |
| 3431 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); | 3465 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
| 3432 } | 3466 } |
| 3433 // Swap register vectors, so the last successful match is in | 3467 // Swap register vectors, so the last successful match is in |
| 3434 // prev_register_vector. | 3468 // prev_register_vector. |
| 3435 Vector<int32_t> tmp = prev_register_vector; | 3469 Vector<int32_t> tmp = prev_register_vector; |
| 3436 prev_register_vector = register_vector; | 3470 prev_register_vector = register_vector; |
| 3437 register_vector = tmp; | 3471 register_vector = tmp; |
| 3438 | 3472 |
| 3439 if (match_end > match_start) { | 3473 if (match_end > match_start) { |
| 3440 pos = match_end; | 3474 pos = match_end; |
| 3441 } else { | 3475 } else { |
| 3442 pos = match_end + 1; | 3476 pos = match_end + 1; |
| 3443 if (pos > subject_length) { | 3477 if (pos > subject_length) { |
| 3444 break; | 3478 break; |
| 3445 } | 3479 } |
| 3446 } | 3480 } |
| 3447 | 3481 |
| 3448 result = RegExpImpl::IrregexpExecOnce(regexp, | 3482 result = RegExpImpl::IrregexpExecOnce(regexp, |
| 3449 subject, | 3483 subject, |
| 3450 pos, | 3484 pos, |
| 3451 register_vector); | 3485 register_vector); |
| 3486 first = false; |
| 3452 } while (result == RegExpImpl::RE_SUCCESS); | 3487 } while (result == RegExpImpl::RE_SUCCESS); |
| 3453 | 3488 |
| 3454 if (result != RegExpImpl::RE_EXCEPTION) { | 3489 if (result != RegExpImpl::RE_EXCEPTION) { |
| 3455 // Finished matching, with at least one match. | 3490 // Finished matching, with at least one match. |
| 3456 if (match_end < subject_length) { | 3491 if (match_end < subject_length) { |
| 3457 ReplacementStringBuilder::AddSubjectSlice(builder, | 3492 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3458 match_end, | 3493 match_end, |
| 3459 subject_length); | 3494 subject_length); |
| 3460 } | 3495 } |
| 3461 | 3496 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3488 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); | 3523 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); |
| 3489 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2); | 3524 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2); |
| 3490 CONVERT_ARG_CHECKED(JSArray, result_array, 3); | 3525 CONVERT_ARG_CHECKED(JSArray, result_array, 3); |
| 3491 | 3526 |
| 3492 ASSERT(last_match_info->HasFastElements()); | 3527 ASSERT(last_match_info->HasFastElements()); |
| 3493 ASSERT(regexp->GetFlags().is_global()); | 3528 ASSERT(regexp->GetFlags().is_global()); |
| 3494 Handle<FixedArray> result_elements; | 3529 Handle<FixedArray> result_elements; |
| 3495 if (result_array->HasFastElements()) { | 3530 if (result_array->HasFastElements()) { |
| 3496 result_elements = | 3531 result_elements = |
| 3497 Handle<FixedArray>(FixedArray::cast(result_array->elements())); | 3532 Handle<FixedArray>(FixedArray::cast(result_array->elements())); |
| 3498 } else { | 3533 } |
| 3534 if (result_elements.is_null() || result_elements->length() < 16) { |
| 3499 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); | 3535 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); |
| 3500 } | 3536 } |
| 3501 FixedArrayBuilder builder(result_elements); | 3537 FixedArrayBuilder builder(result_elements); |
| 3502 | 3538 |
| 3503 if (regexp->TypeTag() == JSRegExp::ATOM) { | 3539 if (regexp->TypeTag() == JSRegExp::ATOM) { |
| 3504 Handle<String> pattern( | 3540 Handle<String> pattern( |
| 3505 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex))); | 3541 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex))); |
| 3506 ASSERT(pattern->IsFlat()); | 3542 ASSERT(pattern->IsFlat()); |
| 3507 if (SearchStringMultiple(isolate, subject, pattern, | 3543 if (SearchStringMultiple(isolate, subject, pattern, |
| 3508 last_match_info, &builder)) { | 3544 last_match_info, &builder)) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3530 if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array); | 3566 if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array); |
| 3531 if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value(); | 3567 if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value(); |
| 3532 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); | 3568 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| 3533 return Failure::Exception(); | 3569 return Failure::Exception(); |
| 3534 } | 3570 } |
| 3535 | 3571 |
| 3536 | 3572 |
| 3537 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) { | 3573 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) { |
| 3538 NoHandleAllocation ha; | 3574 NoHandleAllocation ha; |
| 3539 ASSERT(args.length() == 2); | 3575 ASSERT(args.length() == 2); |
| 3576 CONVERT_SMI_ARG_CHECKED(radix, 1); |
| 3577 RUNTIME_ASSERT(2 <= radix && radix <= 36); |
| 3540 | 3578 |
| 3541 // Fast case where the result is a one character string. | 3579 // Fast case where the result is a one character string. |
| 3542 if (args[0]->IsSmi() && args[1]->IsSmi()) { | 3580 if (args[0]->IsSmi()) { |
| 3543 int value = Smi::cast(args[0])->value(); | 3581 int value = args.smi_at(0); |
| 3544 int radix = Smi::cast(args[1])->value(); | |
| 3545 if (value >= 0 && value < radix) { | 3582 if (value >= 0 && value < radix) { |
| 3546 RUNTIME_ASSERT(radix <= 36); | |
| 3547 // Character array used for conversion. | 3583 // Character array used for conversion. |
| 3548 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; | 3584 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; |
| 3549 return isolate->heap()-> | 3585 return isolate->heap()-> |
| 3550 LookupSingleCharacterStringFromCode(kCharTable[value]); | 3586 LookupSingleCharacterStringFromCode(kCharTable[value]); |
| 3551 } | 3587 } |
| 3552 } | 3588 } |
| 3553 | 3589 |
| 3554 // Slow case. | 3590 // Slow case. |
| 3555 CONVERT_DOUBLE_CHECKED(value, args[0]); | 3591 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
| 3556 if (isnan(value)) { | 3592 if (isnan(value)) { |
| 3557 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3593 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); |
| 3558 } | 3594 } |
| 3559 if (isinf(value)) { | 3595 if (isinf(value)) { |
| 3560 if (value < 0) { | 3596 if (value < 0) { |
| 3561 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3597 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); |
| 3562 } | 3598 } |
| 3563 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3599 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); |
| 3564 } | 3600 } |
| 3565 CONVERT_DOUBLE_CHECKED(radix_number, args[1]); | |
| 3566 int radix = FastD2I(radix_number); | |
| 3567 RUNTIME_ASSERT(2 <= radix && radix <= 36); | |
| 3568 char* str = DoubleToRadixCString(value, radix); | 3601 char* str = DoubleToRadixCString(value, radix); |
| 3569 MaybeObject* result = | 3602 MaybeObject* result = |
| 3570 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 3603 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
| 3571 DeleteArray(str); | 3604 DeleteArray(str); |
| 3572 return result; | 3605 return result; |
| 3573 } | 3606 } |
| 3574 | 3607 |
| 3575 | 3608 |
| 3576 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { | 3609 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { |
| 3577 NoHandleAllocation ha; | 3610 NoHandleAllocation ha; |
| 3578 ASSERT(args.length() == 2); | 3611 ASSERT(args.length() == 2); |
| 3579 | 3612 |
| 3580 CONVERT_DOUBLE_CHECKED(value, args[0]); | 3613 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
| 3581 if (isnan(value)) { | 3614 if (isnan(value)) { |
| 3582 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3615 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); |
| 3583 } | 3616 } |
| 3584 if (isinf(value)) { | 3617 if (isinf(value)) { |
| 3585 if (value < 0) { | 3618 if (value < 0) { |
| 3586 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3619 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); |
| 3587 } | 3620 } |
| 3588 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3621 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); |
| 3589 } | 3622 } |
| 3590 CONVERT_DOUBLE_CHECKED(f_number, args[1]); | 3623 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); |
| 3591 int f = FastD2I(f_number); | 3624 int f = FastD2I(f_number); |
| 3592 RUNTIME_ASSERT(f >= 0); | 3625 RUNTIME_ASSERT(f >= 0); |
| 3593 char* str = DoubleToFixedCString(value, f); | 3626 char* str = DoubleToFixedCString(value, f); |
| 3594 MaybeObject* res = | 3627 MaybeObject* res = |
| 3595 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 3628 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
| 3596 DeleteArray(str); | 3629 DeleteArray(str); |
| 3597 return res; | 3630 return res; |
| 3598 } | 3631 } |
| 3599 | 3632 |
| 3600 | 3633 |
| 3601 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { | 3634 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { |
| 3602 NoHandleAllocation ha; | 3635 NoHandleAllocation ha; |
| 3603 ASSERT(args.length() == 2); | 3636 ASSERT(args.length() == 2); |
| 3604 | 3637 |
| 3605 CONVERT_DOUBLE_CHECKED(value, args[0]); | 3638 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
| 3606 if (isnan(value)) { | 3639 if (isnan(value)) { |
| 3607 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3640 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); |
| 3608 } | 3641 } |
| 3609 if (isinf(value)) { | 3642 if (isinf(value)) { |
| 3610 if (value < 0) { | 3643 if (value < 0) { |
| 3611 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3644 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); |
| 3612 } | 3645 } |
| 3613 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3646 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); |
| 3614 } | 3647 } |
| 3615 CONVERT_DOUBLE_CHECKED(f_number, args[1]); | 3648 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); |
| 3616 int f = FastD2I(f_number); | 3649 int f = FastD2I(f_number); |
| 3617 RUNTIME_ASSERT(f >= -1 && f <= 20); | 3650 RUNTIME_ASSERT(f >= -1 && f <= 20); |
| 3618 char* str = DoubleToExponentialCString(value, f); | 3651 char* str = DoubleToExponentialCString(value, f); |
| 3619 MaybeObject* res = | 3652 MaybeObject* res = |
| 3620 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 3653 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
| 3621 DeleteArray(str); | 3654 DeleteArray(str); |
| 3622 return res; | 3655 return res; |
| 3623 } | 3656 } |
| 3624 | 3657 |
| 3625 | 3658 |
| 3626 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { | 3659 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { |
| 3627 NoHandleAllocation ha; | 3660 NoHandleAllocation ha; |
| 3628 ASSERT(args.length() == 2); | 3661 ASSERT(args.length() == 2); |
| 3629 | 3662 |
| 3630 CONVERT_DOUBLE_CHECKED(value, args[0]); | 3663 CONVERT_DOUBLE_ARG_CHECKED(value, 0); |
| 3631 if (isnan(value)) { | 3664 if (isnan(value)) { |
| 3632 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); | 3665 return isolate->heap()->AllocateStringFromAscii(CStrVector("NaN")); |
| 3633 } | 3666 } |
| 3634 if (isinf(value)) { | 3667 if (isinf(value)) { |
| 3635 if (value < 0) { | 3668 if (value < 0) { |
| 3636 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); | 3669 return isolate->heap()->AllocateStringFromAscii(CStrVector("-Infinity")); |
| 3637 } | 3670 } |
| 3638 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); | 3671 return isolate->heap()->AllocateStringFromAscii(CStrVector("Infinity")); |
| 3639 } | 3672 } |
| 3640 CONVERT_DOUBLE_CHECKED(f_number, args[1]); | 3673 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); |
| 3641 int f = FastD2I(f_number); | 3674 int f = FastD2I(f_number); |
| 3642 RUNTIME_ASSERT(f >= 1 && f <= 21); | 3675 RUNTIME_ASSERT(f >= 1 && f <= 21); |
| 3643 char* str = DoubleToPrecisionCString(value, f); | 3676 char* str = DoubleToPrecisionCString(value, f); |
| 3644 MaybeObject* res = | 3677 MaybeObject* res = |
| 3645 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); | 3678 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); |
| 3646 DeleteArray(str); | 3679 DeleteArray(str); |
| 3647 return res; | 3680 return res; |
| 3648 } | 3681 } |
| 3649 | 3682 |
| 3650 | 3683 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3720 Execution::ToString(key, &has_pending_exception); | 3753 Execution::ToString(key, &has_pending_exception); |
| 3721 if (has_pending_exception) return Failure::Exception(); | 3754 if (has_pending_exception) return Failure::Exception(); |
| 3722 name = Handle<String>::cast(converted); | 3755 name = Handle<String>::cast(converted); |
| 3723 } | 3756 } |
| 3724 | 3757 |
| 3725 // Check if the name is trivially convertible to an index and get | 3758 // Check if the name is trivially convertible to an index and get |
| 3726 // the element if so. | 3759 // the element if so. |
| 3727 if (name->AsArrayIndex(&index)) { | 3760 if (name->AsArrayIndex(&index)) { |
| 3728 return GetElementOrCharAt(isolate, object, index); | 3761 return GetElementOrCharAt(isolate, object, index); |
| 3729 } else { | 3762 } else { |
| 3730 PropertyAttributes attr; | 3763 return object->GetProperty(*name); |
| 3731 return object->GetProperty(*name, &attr); | |
| 3732 } | 3764 } |
| 3733 } | 3765 } |
| 3734 | 3766 |
| 3735 | 3767 |
| 3736 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) { | 3768 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) { |
| 3737 NoHandleAllocation ha; | 3769 NoHandleAllocation ha; |
| 3738 ASSERT(args.length() == 2); | 3770 ASSERT(args.length() == 2); |
| 3739 | 3771 |
| 3740 Handle<Object> object = args.at<Object>(0); | 3772 Handle<Object> object = args.at<Object>(0); |
| 3741 Handle<Object> key = args.at<Object>(1); | 3773 Handle<Object> key = args.at<Object>(1); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3793 if (!receiver->IsGlobalObject()) return value; | 3825 if (!receiver->IsGlobalObject()) return value; |
| 3794 value = JSGlobalPropertyCell::cast(value)->value(); | 3826 value = JSGlobalPropertyCell::cast(value)->value(); |
| 3795 if (!value->IsTheHole()) return value; | 3827 if (!value->IsTheHole()) return value; |
| 3796 // If value is the hole do the general lookup. | 3828 // If value is the hole do the general lookup. |
| 3797 } | 3829 } |
| 3798 } | 3830 } |
| 3799 } else if (args[0]->IsString() && args[1]->IsSmi()) { | 3831 } else if (args[0]->IsString() && args[1]->IsSmi()) { |
| 3800 // Fast case for string indexing using [] with a smi index. | 3832 // Fast case for string indexing using [] with a smi index. |
| 3801 HandleScope scope(isolate); | 3833 HandleScope scope(isolate); |
| 3802 Handle<String> str = args.at<String>(0); | 3834 Handle<String> str = args.at<String>(0); |
| 3803 int index = Smi::cast(args[1])->value(); | 3835 int index = args.smi_at(1); |
| 3804 if (index >= 0 && index < str->length()) { | 3836 if (index >= 0 && index < str->length()) { |
| 3805 Handle<Object> result = GetCharAt(str, index); | 3837 Handle<Object> result = GetCharAt(str, index); |
| 3806 return *result; | 3838 return *result; |
| 3807 } | 3839 } |
| 3808 } | 3840 } |
| 3809 | 3841 |
| 3810 // Fall back to GetObjectProperty. | 3842 // Fall back to GetObjectProperty. |
| 3811 return Runtime::GetObjectProperty(isolate, | 3843 return Runtime::GetObjectProperty(isolate, |
| 3812 args.at<Object>(0), | 3844 args.at<Object>(0), |
| 3813 args.at<Object>(1)); | 3845 args.at<Object>(1)); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3881 // Normalize the elements to enable attributes on the property. | 3913 // Normalize the elements to enable attributes on the property. |
| 3882 if (js_object->IsJSGlobalProxy()) { | 3914 if (js_object->IsJSGlobalProxy()) { |
| 3883 // We do not need to do access checks here since these has already | 3915 // We do not need to do access checks here since these has already |
| 3884 // been performed by the call to GetOwnProperty. | 3916 // been performed by the call to GetOwnProperty. |
| 3885 Handle<Object> proto(js_object->GetPrototype()); | 3917 Handle<Object> proto(js_object->GetPrototype()); |
| 3886 // If proxy is detached, ignore the assignment. Alternatively, | 3918 // If proxy is detached, ignore the assignment. Alternatively, |
| 3887 // we could throw an exception. | 3919 // we could throw an exception. |
| 3888 if (proto->IsNull()) return *obj_value; | 3920 if (proto->IsNull()) return *obj_value; |
| 3889 js_object = Handle<JSObject>::cast(proto); | 3921 js_object = Handle<JSObject>::cast(proto); |
| 3890 } | 3922 } |
| 3891 NormalizeElements(js_object); | 3923 Handle<NumberDictionary> dictionary = NormalizeElements(js_object); |
| 3892 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); | |
| 3893 // Make sure that we never go back to fast case. | 3924 // Make sure that we never go back to fast case. |
| 3894 dictionary->set_requires_slow_elements(); | 3925 dictionary->set_requires_slow_elements(); |
| 3895 PropertyDetails details = PropertyDetails(attr, NORMAL); | 3926 PropertyDetails details = PropertyDetails(attr, NORMAL); |
| 3896 NumberDictionarySet(dictionary, index, obj_value, details); | 3927 Handle<NumberDictionary> extended_dictionary = |
| 3928 NumberDictionarySet(dictionary, index, obj_value, details); |
| 3929 if (*extended_dictionary != *dictionary) { |
| 3930 if (js_object->GetElementsKind() == |
| 3931 JSObject::NON_STRICT_ARGUMENTS_ELEMENTS) { |
| 3932 FixedArray::cast(js_object->elements())->set(1, *extended_dictionary); |
| 3933 } else { |
| 3934 js_object->set_elements(*extended_dictionary); |
| 3935 } |
| 3936 } |
| 3897 return *obj_value; | 3937 return *obj_value; |
| 3898 } | 3938 } |
| 3899 | 3939 |
| 3900 LookupResult result; | 3940 LookupResult result; |
| 3901 js_object->LookupRealNamedProperty(*name, &result); | 3941 js_object->LocalLookupRealNamedProperty(*name, &result); |
| 3902 | 3942 |
| 3903 // To be compatible with safari we do not change the value on API objects | 3943 // To be compatible with safari we do not change the value on API objects |
| 3904 // in defineProperty. Firefox disagrees here, and actually changes the value. | 3944 // in defineProperty. Firefox disagrees here, and actually changes the value. |
| 3905 if (result.IsProperty() && | 3945 if (result.IsProperty() && |
| 3906 (result.type() == CALLBACKS) && | 3946 (result.type() == CALLBACKS) && |
| 3907 result.GetCallbackObject()->IsAccessorInfo()) { | 3947 result.GetCallbackObject()->IsAccessorInfo()) { |
| 3908 return isolate->heap()->undefined_value(); | 3948 return isolate->heap()->undefined_value(); |
| 3909 } | 3949 } |
| 3910 | 3950 |
| 3911 // Take special care when attributes are different and there is already | 3951 // Take special care when attributes are different and there is already |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3931 } | 3971 } |
| 3932 | 3972 |
| 3933 return Runtime::ForceSetObjectProperty(isolate, | 3973 return Runtime::ForceSetObjectProperty(isolate, |
| 3934 js_object, | 3974 js_object, |
| 3935 name, | 3975 name, |
| 3936 obj_value, | 3976 obj_value, |
| 3937 attr); | 3977 attr); |
| 3938 } | 3978 } |
| 3939 | 3979 |
| 3940 | 3980 |
| 3981 // Special case for elements if any of the flags are true. |
| 3982 // If elements are in fast case we always implicitly assume that: |
| 3983 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. |
| 3984 static MaybeObject* NormalizeObjectSetElement(Isolate* isolate, |
| 3985 Handle<JSObject> js_object, |
| 3986 uint32_t index, |
| 3987 Handle<Object> value, |
| 3988 PropertyAttributes attr) { |
| 3989 // Normalize the elements to enable attributes on the property. |
| 3990 Handle<NumberDictionary> dictionary = NormalizeElements(js_object); |
| 3991 // Make sure that we never go back to fast case. |
| 3992 dictionary->set_requires_slow_elements(); |
| 3993 PropertyDetails details = PropertyDetails(attr, NORMAL); |
| 3994 Handle<NumberDictionary> extended_dictionary = |
| 3995 NumberDictionarySet(dictionary, index, value, details); |
| 3996 if (*extended_dictionary != *dictionary) { |
| 3997 js_object->set_elements(*extended_dictionary); |
| 3998 } |
| 3999 return *value; |
| 4000 } |
| 4001 |
| 4002 |
| 3941 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, | 4003 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, |
| 3942 Handle<Object> object, | 4004 Handle<Object> object, |
| 3943 Handle<Object> key, | 4005 Handle<Object> key, |
| 3944 Handle<Object> value, | 4006 Handle<Object> value, |
| 3945 PropertyAttributes attr, | 4007 PropertyAttributes attr, |
| 3946 StrictModeFlag strict_mode) { | 4008 StrictModeFlag strict_mode) { |
| 3947 HandleScope scope(isolate); | 4009 HandleScope scope(isolate); |
| 3948 | 4010 |
| 3949 if (object->IsUndefined() || object->IsNull()) { | 4011 if (object->IsUndefined() || object->IsNull()) { |
| 3950 Handle<Object> args[2] = { key, object }; | 4012 Handle<Object> args[2] = { key, object }; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3966 // of a string using [] notation. We need to support this too in | 4028 // of a string using [] notation. We need to support this too in |
| 3967 // JavaScript. | 4029 // JavaScript. |
| 3968 // In the case of a String object we just need to redirect the assignment to | 4030 // In the case of a String object we just need to redirect the assignment to |
| 3969 // the underlying string if the index is in range. Since the underlying | 4031 // the underlying string if the index is in range. Since the underlying |
| 3970 // string does nothing with the assignment then we can ignore such | 4032 // string does nothing with the assignment then we can ignore such |
| 3971 // assignments. | 4033 // assignments. |
| 3972 if (js_object->IsStringObjectWithCharacterAt(index)) { | 4034 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 3973 return *value; | 4035 return *value; |
| 3974 } | 4036 } |
| 3975 | 4037 |
| 4038 if (((attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0)) { |
| 4039 return NormalizeObjectSetElement(isolate, js_object, index, value, attr); |
| 4040 } |
| 4041 |
| 3976 Handle<Object> result = SetElement(js_object, index, value, strict_mode); | 4042 Handle<Object> result = SetElement(js_object, index, value, strict_mode); |
| 3977 if (result.is_null()) return Failure::Exception(); | 4043 if (result.is_null()) return Failure::Exception(); |
| 3978 return *value; | 4044 return *value; |
| 3979 } | 4045 } |
| 3980 | 4046 |
| 3981 if (key->IsString()) { | 4047 if (key->IsString()) { |
| 3982 Handle<Object> result; | 4048 Handle<Object> result; |
| 3983 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 4049 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 4050 if (((attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0)) { |
| 4051 return NormalizeObjectSetElement(isolate, |
| 4052 js_object, |
| 4053 index, |
| 4054 value, |
| 4055 attr); |
| 4056 } |
| 3984 result = SetElement(js_object, index, value, strict_mode); | 4057 result = SetElement(js_object, index, value, strict_mode); |
| 3985 } else { | 4058 } else { |
| 3986 Handle<String> key_string = Handle<String>::cast(key); | 4059 Handle<String> key_string = Handle<String>::cast(key); |
| 3987 key_string->TryFlatten(); | 4060 key_string->TryFlatten(); |
| 3988 result = SetProperty(js_object, key_string, value, attr, strict_mode); | 4061 result = SetProperty(js_object, key_string, value, attr, strict_mode); |
| 3989 } | 4062 } |
| 3990 if (result.is_null()) return Failure::Exception(); | 4063 if (result.is_null()) return Failure::Exception(); |
| 3991 return *value; | 4064 return *value; |
| 3992 } | 4065 } |
| 3993 | 4066 |
| 3994 // Call-back into JavaScript to convert the key to a string. | 4067 // Call-back into JavaScript to convert the key to a string. |
| 3995 bool has_pending_exception = false; | 4068 bool has_pending_exception = false; |
| 3996 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 4069 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 3997 if (has_pending_exception) return Failure::Exception(); | 4070 if (has_pending_exception) return Failure::Exception(); |
| 3998 Handle<String> name = Handle<String>::cast(converted); | 4071 Handle<String> name = Handle<String>::cast(converted); |
| 3999 | 4072 |
| 4000 if (name->AsArrayIndex(&index)) { | 4073 if (name->AsArrayIndex(&index)) { |
| 4001 return js_object->SetElement(index, *value, strict_mode); | 4074 return js_object->SetElement(index, *value, strict_mode, true); |
| 4002 } else { | 4075 } else { |
| 4003 return js_object->SetProperty(*name, *value, attr, strict_mode); | 4076 return js_object->SetProperty(*name, *value, attr, strict_mode); |
| 4004 } | 4077 } |
| 4005 } | 4078 } |
| 4006 | 4079 |
| 4007 | 4080 |
| 4008 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, | 4081 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, |
| 4009 Handle<JSObject> js_object, | 4082 Handle<JSObject> js_object, |
| 4010 Handle<Object> key, | 4083 Handle<Object> key, |
| 4011 Handle<Object> value, | 4084 Handle<Object> value, |
| 4012 PropertyAttributes attr) { | 4085 PropertyAttributes attr) { |
| 4013 HandleScope scope(isolate); | 4086 HandleScope scope(isolate); |
| 4014 | 4087 |
| 4015 // Check if the given key is an array index. | 4088 // Check if the given key is an array index. |
| 4016 uint32_t index; | 4089 uint32_t index; |
| 4017 if (key->ToArrayIndex(&index)) { | 4090 if (key->ToArrayIndex(&index)) { |
| 4018 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 4091 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
| 4019 // of a string using [] notation. We need to support this too in | 4092 // of a string using [] notation. We need to support this too in |
| 4020 // JavaScript. | 4093 // JavaScript. |
| 4021 // In the case of a String object we just need to redirect the assignment to | 4094 // In the case of a String object we just need to redirect the assignment to |
| 4022 // the underlying string if the index is in range. Since the underlying | 4095 // the underlying string if the index is in range. Since the underlying |
| 4023 // string does nothing with the assignment then we can ignore such | 4096 // string does nothing with the assignment then we can ignore such |
| 4024 // assignments. | 4097 // assignments. |
| 4025 if (js_object->IsStringObjectWithCharacterAt(index)) { | 4098 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 4026 return *value; | 4099 return *value; |
| 4027 } | 4100 } |
| 4028 | 4101 |
| 4029 return js_object->SetElement(index, *value, kNonStrictMode); | 4102 return js_object->SetElement(index, *value, kNonStrictMode, true); |
| 4030 } | 4103 } |
| 4031 | 4104 |
| 4032 if (key->IsString()) { | 4105 if (key->IsString()) { |
| 4033 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 4106 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 4034 return js_object->SetElement(index, *value, kNonStrictMode); | 4107 return js_object->SetElement(index, *value, kNonStrictMode, true); |
| 4035 } else { | 4108 } else { |
| 4036 Handle<String> key_string = Handle<String>::cast(key); | 4109 Handle<String> key_string = Handle<String>::cast(key); |
| 4037 key_string->TryFlatten(); | 4110 key_string->TryFlatten(); |
| 4038 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, | 4111 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, |
| 4039 *value, | 4112 *value, |
| 4040 attr); | 4113 attr); |
| 4041 } | 4114 } |
| 4042 } | 4115 } |
| 4043 | 4116 |
| 4044 // Call-back into JavaScript to convert the key to a string. | 4117 // Call-back into JavaScript to convert the key to a string. |
| 4045 bool has_pending_exception = false; | 4118 bool has_pending_exception = false; |
| 4046 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 4119 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 4047 if (has_pending_exception) return Failure::Exception(); | 4120 if (has_pending_exception) return Failure::Exception(); |
| 4048 Handle<String> name = Handle<String>::cast(converted); | 4121 Handle<String> name = Handle<String>::cast(converted); |
| 4049 | 4122 |
| 4050 if (name->AsArrayIndex(&index)) { | 4123 if (name->AsArrayIndex(&index)) { |
| 4051 return js_object->SetElement(index, *value, kNonStrictMode); | 4124 return js_object->SetElement(index, *value, kNonStrictMode, true); |
| 4052 } else { | 4125 } else { |
| 4053 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); | 4126 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); |
| 4054 } | 4127 } |
| 4055 } | 4128 } |
| 4056 | 4129 |
| 4057 | 4130 |
| 4058 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, | 4131 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, |
| 4059 Handle<JSObject> js_object, | 4132 Handle<JSObject> js_object, |
| 4060 Handle<Object> key) { | 4133 Handle<Object> key) { |
| 4061 HandleScope scope(isolate); | 4134 HandleScope scope(isolate); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4092 } | 4165 } |
| 4093 | 4166 |
| 4094 | 4167 |
| 4095 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) { | 4168 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) { |
| 4096 NoHandleAllocation ha; | 4169 NoHandleAllocation ha; |
| 4097 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); | 4170 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); |
| 4098 | 4171 |
| 4099 Handle<Object> object = args.at<Object>(0); | 4172 Handle<Object> object = args.at<Object>(0); |
| 4100 Handle<Object> key = args.at<Object>(1); | 4173 Handle<Object> key = args.at<Object>(1); |
| 4101 Handle<Object> value = args.at<Object>(2); | 4174 Handle<Object> value = args.at<Object>(2); |
| 4102 CONVERT_SMI_CHECKED(unchecked_attributes, args[3]); | 4175 CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3); |
| 4103 RUNTIME_ASSERT( | 4176 RUNTIME_ASSERT( |
| 4104 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | 4177 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
| 4105 // Compute attributes. | 4178 // Compute attributes. |
| 4106 PropertyAttributes attributes = | 4179 PropertyAttributes attributes = |
| 4107 static_cast<PropertyAttributes>(unchecked_attributes); | 4180 static_cast<PropertyAttributes>(unchecked_attributes); |
| 4108 | 4181 |
| 4109 StrictModeFlag strict_mode = kNonStrictMode; | 4182 StrictModeFlag strict_mode = kNonStrictMode; |
| 4110 if (args.length() == 5) { | 4183 if (args.length() == 5) { |
| 4111 CONVERT_SMI_CHECKED(strict_unchecked, args[4]); | 4184 CONVERT_SMI_ARG_CHECKED(strict_unchecked, 4); |
| 4112 RUNTIME_ASSERT(strict_unchecked == kStrictMode || | 4185 RUNTIME_ASSERT(strict_unchecked == kStrictMode || |
| 4113 strict_unchecked == kNonStrictMode); | 4186 strict_unchecked == kNonStrictMode); |
| 4114 strict_mode = static_cast<StrictModeFlag>(strict_unchecked); | 4187 strict_mode = static_cast<StrictModeFlag>(strict_unchecked); |
| 4115 } | 4188 } |
| 4116 | 4189 |
| 4117 return Runtime::SetObjectProperty(isolate, | 4190 return Runtime::SetObjectProperty(isolate, |
| 4118 object, | 4191 object, |
| 4119 key, | 4192 key, |
| 4120 value, | 4193 value, |
| 4121 attributes, | 4194 attributes, |
| 4122 strict_mode); | 4195 strict_mode); |
| 4123 } | 4196 } |
| 4124 | 4197 |
| 4125 | 4198 |
| 4126 // Set the ES5 native flag on the function. | 4199 // Set the native flag on the function. |
| 4127 // This is used to decide if we should transform null and undefined | 4200 // This is used to decide if we should transform null and undefined |
| 4128 // into the global object when doing call and apply. | 4201 // into the global object when doing call and apply. |
| 4129 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetES5Flag) { | 4202 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) { |
| 4130 NoHandleAllocation ha; | 4203 NoHandleAllocation ha; |
| 4131 RUNTIME_ASSERT(args.length() == 1); | 4204 RUNTIME_ASSERT(args.length() == 1); |
| 4132 | 4205 |
| 4133 Handle<Object> object = args.at<Object>(0); | 4206 Handle<Object> object = args.at<Object>(0); |
| 4134 | 4207 |
| 4135 if (object->IsJSFunction()) { | 4208 if (object->IsJSFunction()) { |
| 4136 JSFunction* func = JSFunction::cast(*object); | 4209 JSFunction* func = JSFunction::cast(*object); |
| 4137 func->shared()->set_es5_native(true); | 4210 func->shared()->set_native(true); |
| 4138 } | 4211 } |
| 4139 return isolate->heap()->undefined_value(); | 4212 return isolate->heap()->undefined_value(); |
| 4140 } | 4213 } |
| 4141 | 4214 |
| 4142 | 4215 |
| 4143 // Set a local property, even if it is READ_ONLY. If the property does not | 4216 // Set a local property, even if it is READ_ONLY. If the property does not |
| 4144 // exist, it will be added with attributes NONE. | 4217 // exist, it will be added with attributes NONE. |
| 4145 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) { | 4218 RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) { |
| 4146 NoHandleAllocation ha; | 4219 NoHandleAllocation ha; |
| 4147 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); | 4220 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4162 SetLocalPropertyIgnoreAttributes(name, args[2], attributes); | 4235 SetLocalPropertyIgnoreAttributes(name, args[2], attributes); |
| 4163 } | 4236 } |
| 4164 | 4237 |
| 4165 | 4238 |
| 4166 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) { | 4239 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) { |
| 4167 NoHandleAllocation ha; | 4240 NoHandleAllocation ha; |
| 4168 ASSERT(args.length() == 3); | 4241 ASSERT(args.length() == 3); |
| 4169 | 4242 |
| 4170 CONVERT_CHECKED(JSObject, object, args[0]); | 4243 CONVERT_CHECKED(JSObject, object, args[0]); |
| 4171 CONVERT_CHECKED(String, key, args[1]); | 4244 CONVERT_CHECKED(String, key, args[1]); |
| 4172 CONVERT_SMI_CHECKED(strict, args[2]); | 4245 CONVERT_SMI_ARG_CHECKED(strict, 2); |
| 4173 return object->DeleteProperty(key, (strict == kStrictMode) | 4246 return object->DeleteProperty(key, (strict == kStrictMode) |
| 4174 ? JSObject::STRICT_DELETION | 4247 ? JSObject::STRICT_DELETION |
| 4175 : JSObject::NORMAL_DELETION); | 4248 : JSObject::NORMAL_DELETION); |
| 4176 } | 4249 } |
| 4177 | 4250 |
| 4178 | 4251 |
| 4179 static Object* HasLocalPropertyImplementation(Isolate* isolate, | 4252 static Object* HasLocalPropertyImplementation(Isolate* isolate, |
| 4180 Handle<JSObject> object, | 4253 Handle<JSObject> object, |
| 4181 Handle<String> key) { | 4254 Handle<String> key) { |
| 4182 if (object->HasLocalProperty(*key)) return isolate->heap()->true_value(); | 4255 if (object->HasLocalProperty(*key)) return isolate->heap()->true_value(); |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4633 switch (instance_type) { | 4706 switch (instance_type) { |
| 4634 case ODDBALL_TYPE: | 4707 case ODDBALL_TYPE: |
| 4635 if (heap_obj->IsTrue() || heap_obj->IsFalse()) { | 4708 if (heap_obj->IsTrue() || heap_obj->IsFalse()) { |
| 4636 return isolate->heap()->boolean_symbol(); | 4709 return isolate->heap()->boolean_symbol(); |
| 4637 } | 4710 } |
| 4638 if (heap_obj->IsNull()) { | 4711 if (heap_obj->IsNull()) { |
| 4639 return isolate->heap()->object_symbol(); | 4712 return isolate->heap()->object_symbol(); |
| 4640 } | 4713 } |
| 4641 ASSERT(heap_obj->IsUndefined()); | 4714 ASSERT(heap_obj->IsUndefined()); |
| 4642 return isolate->heap()->undefined_symbol(); | 4715 return isolate->heap()->undefined_symbol(); |
| 4643 case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE: | 4716 case JS_FUNCTION_TYPE: |
| 4644 return isolate->heap()->function_symbol(); | 4717 return isolate->heap()->function_symbol(); |
| 4645 default: | 4718 default: |
| 4646 // For any kind of object not handled above, the spec rule for | 4719 // For any kind of object not handled above, the spec rule for |
| 4647 // host objects gives that it is okay to return "object" | 4720 // host objects gives that it is okay to return "object" |
| 4648 return isolate->heap()->object_symbol(); | 4721 return isolate->heap()->object_symbol(); |
| 4649 } | 4722 } |
| 4650 } | 4723 } |
| 4651 | 4724 |
| 4652 | 4725 |
| 4653 static bool AreDigits(const char*s, int from, int to) { | 4726 static bool AreDigits(const char*s, int from, int to) { |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5007 | 5080 |
| 5008 | 5081 |
| 5009 // For a string that is less than 32k characters it should always be | 5082 // For a string that is less than 32k characters it should always be |
| 5010 // possible to allocate it in new space. | 5083 // possible to allocate it in new space. |
| 5011 static const int kMaxGuaranteedNewSpaceString = 32 * 1024; | 5084 static const int kMaxGuaranteedNewSpaceString = 32 * 1024; |
| 5012 | 5085 |
| 5013 | 5086 |
| 5014 // Doing JSON quoting cannot make the string more than this many times larger. | 5087 // Doing JSON quoting cannot make the string more than this many times larger. |
| 5015 static const int kJsonQuoteWorstCaseBlowup = 6; | 5088 static const int kJsonQuoteWorstCaseBlowup = 6; |
| 5016 | 5089 |
| 5090 static const int kSpaceForQuotesAndComma = 3; |
| 5091 static const int kSpaceForBrackets = 2; |
| 5017 | 5092 |
| 5018 // Covers the entire ASCII range (all other characters are unchanged by JSON | 5093 // Covers the entire ASCII range (all other characters are unchanged by JSON |
| 5019 // quoting). | 5094 // quoting). |
| 5020 static const byte JsonQuoteLengths[kQuoteTableLength] = { | 5095 static const byte JsonQuoteLengths[kQuoteTableLength] = { |
| 5021 6, 6, 6, 6, 6, 6, 6, 6, | 5096 6, 6, 6, 6, 6, 6, 6, 6, |
| 5022 2, 2, 2, 6, 2, 2, 6, 6, | 5097 2, 2, 2, 6, 2, 2, 6, 6, |
| 5023 6, 6, 6, 6, 6, 6, 6, 6, | 5098 6, 6, 6, 6, 6, 6, 6, 6, |
| 5024 6, 6, 6, 6, 6, 6, 6, 6, | 5099 6, 6, 6, 6, 6, 6, 6, 6, |
| 5025 1, 1, 2, 1, 1, 1, 1, 1, | 5100 1, 1, 2, 1, 1, 1, 1, 1, |
| 5026 1, 1, 1, 1, 1, 1, 1, 1, | 5101 1, 1, 1, 1, 1, 1, 1, 1, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5094 for (int i = 0; i < len; i++) { | 5169 for (int i = 0; i < len; i++) { |
| 5095 *write_cursor++ = *replacement++; | 5170 *write_cursor++ = *replacement++; |
| 5096 } | 5171 } |
| 5097 } | 5172 } |
| 5098 } | 5173 } |
| 5099 *(write_cursor++) = '"'; | 5174 *(write_cursor++) = '"'; |
| 5100 return new_string; | 5175 return new_string; |
| 5101 } | 5176 } |
| 5102 | 5177 |
| 5103 | 5178 |
| 5179 template <typename SinkChar, typename SourceChar> |
| 5180 static inline SinkChar* WriteQuoteJsonString( |
| 5181 Isolate* isolate, |
| 5182 SinkChar* write_cursor, |
| 5183 Vector<const SourceChar> characters) { |
| 5184 // SinkChar is only char if SourceChar is guaranteed to be char. |
| 5185 ASSERT(sizeof(SinkChar) >= sizeof(SourceChar)); |
| 5186 const SourceChar* read_cursor = characters.start(); |
| 5187 const SourceChar* end = read_cursor + characters.length(); |
| 5188 *(write_cursor++) = '"'; |
| 5189 while (read_cursor < end) { |
| 5190 SourceChar c = *(read_cursor++); |
| 5191 if (sizeof(SourceChar) > 1u && |
| 5192 static_cast<unsigned>(c) >= kQuoteTableLength) { |
| 5193 *(write_cursor++) = static_cast<SinkChar>(c); |
| 5194 } else { |
| 5195 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; |
| 5196 const char* replacement = JsonQuotes + |
| 5197 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; |
| 5198 write_cursor[0] = replacement[0]; |
| 5199 if (len > 1) { |
| 5200 write_cursor[1] = replacement[1]; |
| 5201 if (len > 2) { |
| 5202 ASSERT(len == 6); |
| 5203 write_cursor[2] = replacement[2]; |
| 5204 write_cursor[3] = replacement[3]; |
| 5205 write_cursor[4] = replacement[4]; |
| 5206 write_cursor[5] = replacement[5]; |
| 5207 } |
| 5208 } |
| 5209 write_cursor += len; |
| 5210 } |
| 5211 } |
| 5212 *(write_cursor++) = '"'; |
| 5213 return write_cursor; |
| 5214 } |
| 5215 |
| 5216 |
| 5104 template <typename Char, typename StringType, bool comma> | 5217 template <typename Char, typename StringType, bool comma> |
| 5105 static MaybeObject* QuoteJsonString(Isolate* isolate, | 5218 static MaybeObject* QuoteJsonString(Isolate* isolate, |
| 5106 Vector<const Char> characters) { | 5219 Vector<const Char> characters) { |
| 5107 int length = characters.length(); | 5220 int length = characters.length(); |
| 5108 isolate->counters()->quote_json_char_count()->Increment(length); | 5221 isolate->counters()->quote_json_char_count()->Increment(length); |
| 5109 const int kSpaceForQuotes = 2 + (comma ? 1 :0); | 5222 int worst_case_length = |
| 5110 int worst_case_length = length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotes; | 5223 length * kJsonQuoteWorstCaseBlowup + kSpaceForQuotesAndComma; |
| 5111 if (worst_case_length > kMaxGuaranteedNewSpaceString) { | 5224 if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
| 5112 return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters); | 5225 return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters); |
| 5113 } | 5226 } |
| 5114 | 5227 |
| 5115 MaybeObject* new_alloc = AllocateRawString<StringType>(isolate, | 5228 MaybeObject* new_alloc = AllocateRawString<StringType>(isolate, |
| 5116 worst_case_length); | 5229 worst_case_length); |
| 5117 Object* new_object; | 5230 Object* new_object; |
| 5118 if (!new_alloc->ToObject(&new_object)) { | 5231 if (!new_alloc->ToObject(&new_object)) { |
| 5119 return new_alloc; | 5232 return new_alloc; |
| 5120 } | 5233 } |
| 5121 if (!isolate->heap()->new_space()->Contains(new_object)) { | 5234 if (!isolate->heap()->new_space()->Contains(new_object)) { |
| 5122 // Even if our string is small enough to fit in new space we still have to | 5235 // Even if our string is small enough to fit in new space we still have to |
| 5123 // handle it being allocated in old space as may happen in the third | 5236 // handle it being allocated in old space as may happen in the third |
| 5124 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in | 5237 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
| 5125 // CEntryStub::GenerateCore. | 5238 // CEntryStub::GenerateCore. |
| 5126 return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters); | 5239 return SlowQuoteJsonString<Char, StringType, comma>(isolate, characters); |
| 5127 } | 5240 } |
| 5128 StringType* new_string = StringType::cast(new_object); | 5241 StringType* new_string = StringType::cast(new_object); |
| 5129 ASSERT(isolate->heap()->new_space()->Contains(new_string)); | 5242 ASSERT(isolate->heap()->new_space()->Contains(new_string)); |
| 5130 | 5243 |
| 5131 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); | 5244 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| 5132 Char* write_cursor = reinterpret_cast<Char*>( | 5245 Char* write_cursor = reinterpret_cast<Char*>( |
| 5133 new_string->address() + SeqAsciiString::kHeaderSize); | 5246 new_string->address() + SeqAsciiString::kHeaderSize); |
| 5134 if (comma) *(write_cursor++) = ','; | 5247 if (comma) *(write_cursor++) = ','; |
| 5135 *(write_cursor++) = '"'; | 5248 write_cursor = WriteQuoteJsonString<Char, Char>(isolate, |
| 5136 | 5249 write_cursor, |
| 5137 const Char* read_cursor = characters.start(); | 5250 characters); |
| 5138 const Char* end = read_cursor + length; | |
| 5139 while (read_cursor < end) { | |
| 5140 Char c = *(read_cursor++); | |
| 5141 if (sizeof(Char) > 1u && static_cast<unsigned>(c) >= kQuoteTableLength) { | |
| 5142 *(write_cursor++) = c; | |
| 5143 } else { | |
| 5144 int len = JsonQuoteLengths[static_cast<unsigned>(c)]; | |
| 5145 const char* replacement = JsonQuotes + | |
| 5146 static_cast<unsigned>(c) * kJsonQuotesCharactersPerEntry; | |
| 5147 write_cursor[0] = replacement[0]; | |
| 5148 if (len > 1) { | |
| 5149 write_cursor[1] = replacement[1]; | |
| 5150 if (len > 2) { | |
| 5151 ASSERT(len == 6); | |
| 5152 write_cursor[2] = replacement[2]; | |
| 5153 write_cursor[3] = replacement[3]; | |
| 5154 write_cursor[4] = replacement[4]; | |
| 5155 write_cursor[5] = replacement[5]; | |
| 5156 } | |
| 5157 } | |
| 5158 write_cursor += len; | |
| 5159 } | |
| 5160 } | |
| 5161 *(write_cursor++) = '"'; | |
| 5162 | |
| 5163 int final_length = static_cast<int>( | 5251 int final_length = static_cast<int>( |
| 5164 write_cursor - reinterpret_cast<Char*>( | 5252 write_cursor - reinterpret_cast<Char*>( |
| 5165 new_string->address() + SeqAsciiString::kHeaderSize)); | 5253 new_string->address() + SeqAsciiString::kHeaderSize)); |
| 5166 isolate->heap()->new_space()-> | 5254 isolate->heap()->new_space()-> |
| 5167 template ShrinkStringAtAllocationBoundary<StringType>( | 5255 template ShrinkStringAtAllocationBoundary<StringType>( |
| 5168 new_string, final_length); | 5256 new_string, final_length); |
| 5169 return new_string; | 5257 return new_string; |
| 5170 } | 5258 } |
| 5171 | 5259 |
| 5172 | 5260 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5206 } | 5294 } |
| 5207 if (str->IsTwoByteRepresentation()) { | 5295 if (str->IsTwoByteRepresentation()) { |
| 5208 return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate, | 5296 return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate, |
| 5209 str->ToUC16Vector()); | 5297 str->ToUC16Vector()); |
| 5210 } else { | 5298 } else { |
| 5211 return QuoteJsonString<char, SeqAsciiString, true>(isolate, | 5299 return QuoteJsonString<char, SeqAsciiString, true>(isolate, |
| 5212 str->ToAsciiVector()); | 5300 str->ToAsciiVector()); |
| 5213 } | 5301 } |
| 5214 } | 5302 } |
| 5215 | 5303 |
| 5304 |
| 5305 template <typename Char, typename StringType> |
| 5306 static MaybeObject* QuoteJsonStringArray(Isolate* isolate, |
| 5307 FixedArray* array, |
| 5308 int worst_case_length) { |
| 5309 int length = array->length(); |
| 5310 |
| 5311 MaybeObject* new_alloc = AllocateRawString<StringType>(isolate, |
| 5312 worst_case_length); |
| 5313 Object* new_object; |
| 5314 if (!new_alloc->ToObject(&new_object)) { |
| 5315 return new_alloc; |
| 5316 } |
| 5317 if (!isolate->heap()->new_space()->Contains(new_object)) { |
| 5318 // Even if our string is small enough to fit in new space we still have to |
| 5319 // handle it being allocated in old space as may happen in the third |
| 5320 // attempt. See CALL_AND_RETRY in heap-inl.h and similar code in |
| 5321 // CEntryStub::GenerateCore. |
| 5322 return isolate->heap()->undefined_value(); |
| 5323 } |
| 5324 AssertNoAllocation no_gc; |
| 5325 StringType* new_string = StringType::cast(new_object); |
| 5326 ASSERT(isolate->heap()->new_space()->Contains(new_string)); |
| 5327 |
| 5328 STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqAsciiString::kHeaderSize); |
| 5329 Char* write_cursor = reinterpret_cast<Char*>( |
| 5330 new_string->address() + SeqAsciiString::kHeaderSize); |
| 5331 *(write_cursor++) = '['; |
| 5332 for (int i = 0; i < length; i++) { |
| 5333 if (i != 0) *(write_cursor++) = ','; |
| 5334 String* str = String::cast(array->get(i)); |
| 5335 if (str->IsTwoByteRepresentation()) { |
| 5336 write_cursor = WriteQuoteJsonString<Char, uc16>(isolate, |
| 5337 write_cursor, |
| 5338 str->ToUC16Vector()); |
| 5339 } else { |
| 5340 write_cursor = WriteQuoteJsonString<Char, char>(isolate, |
| 5341 write_cursor, |
| 5342 str->ToAsciiVector()); |
| 5343 } |
| 5344 } |
| 5345 *(write_cursor++) = ']'; |
| 5346 |
| 5347 int final_length = static_cast<int>( |
| 5348 write_cursor - reinterpret_cast<Char*>( |
| 5349 new_string->address() + SeqAsciiString::kHeaderSize)); |
| 5350 isolate->heap()->new_space()-> |
| 5351 template ShrinkStringAtAllocationBoundary<StringType>( |
| 5352 new_string, final_length); |
| 5353 return new_string; |
| 5354 } |
| 5355 |
| 5356 |
| 5357 RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { |
| 5358 NoHandleAllocation ha; |
| 5359 ASSERT(args.length() == 1); |
| 5360 CONVERT_CHECKED(JSArray, array, args[0]); |
| 5361 |
| 5362 if (!array->HasFastElements()) return isolate->heap()->undefined_value(); |
| 5363 FixedArray* elements = FixedArray::cast(array->elements()); |
| 5364 int n = elements->length(); |
| 5365 bool ascii = true; |
| 5366 int total_length = 0; |
| 5367 |
| 5368 for (int i = 0; i < n; i++) { |
| 5369 Object* elt = elements->get(i); |
| 5370 if (!elt->IsString()) return isolate->heap()->undefined_value(); |
| 5371 String* element = String::cast(elt); |
| 5372 if (!element->IsFlat()) return isolate->heap()->undefined_value(); |
| 5373 total_length += element->length(); |
| 5374 if (ascii && element->IsTwoByteRepresentation()) { |
| 5375 ascii = false; |
| 5376 } |
| 5377 } |
| 5378 |
| 5379 int worst_case_length = |
| 5380 kSpaceForBrackets + n * kSpaceForQuotesAndComma |
| 5381 + total_length * kJsonQuoteWorstCaseBlowup; |
| 5382 |
| 5383 if (worst_case_length > kMaxGuaranteedNewSpaceString) { |
| 5384 return isolate->heap()->undefined_value(); |
| 5385 } |
| 5386 |
| 5387 if (ascii) { |
| 5388 return QuoteJsonStringArray<char, SeqAsciiString>(isolate, |
| 5389 elements, |
| 5390 worst_case_length); |
| 5391 } else { |
| 5392 return QuoteJsonStringArray<uc16, SeqTwoByteString>(isolate, |
| 5393 elements, |
| 5394 worst_case_length); |
| 5395 } |
| 5396 } |
| 5397 |
| 5398 |
| 5216 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { | 5399 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { |
| 5217 NoHandleAllocation ha; | 5400 NoHandleAllocation ha; |
| 5218 | 5401 |
| 5219 CONVERT_CHECKED(String, s, args[0]); | 5402 CONVERT_CHECKED(String, s, args[0]); |
| 5220 CONVERT_SMI_CHECKED(radix, args[1]); | 5403 CONVERT_SMI_ARG_CHECKED(radix, 1); |
| 5221 | 5404 |
| 5222 s->TryFlatten(); | 5405 s->TryFlatten(); |
| 5223 | 5406 |
| 5224 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); | 5407 RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36)); |
| 5225 double value = StringToInt(isolate->unicode_cache(), s, radix); | 5408 double value = StringToInt(isolate->unicode_cache(), s, radix); |
| 5226 return isolate->heap()->NumberFromDouble(value); | 5409 return isolate->heap()->NumberFromDouble(value); |
| 5227 } | 5410 } |
| 5228 | 5411 |
| 5229 | 5412 |
| 5230 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) { | 5413 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) { |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5557 int right = length; | 5740 int right = length; |
| 5558 if (trimRight) { | 5741 if (trimRight) { |
| 5559 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { | 5742 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { |
| 5560 right--; | 5743 right--; |
| 5561 } | 5744 } |
| 5562 } | 5745 } |
| 5563 return s->SubString(left, right); | 5746 return s->SubString(left, right); |
| 5564 } | 5747 } |
| 5565 | 5748 |
| 5566 | 5749 |
| 5750 void FindAsciiStringIndices(Vector<const char> subject, |
| 5751 char pattern, |
| 5752 ZoneList<int>* indices, |
| 5753 unsigned int limit) { |
| 5754 ASSERT(limit > 0); |
| 5755 // Collect indices of pattern in subject using memchr. |
| 5756 // Stop after finding at most limit values. |
| 5757 const char* subject_start = reinterpret_cast<const char*>(subject.start()); |
| 5758 const char* subject_end = subject_start + subject.length(); |
| 5759 const char* pos = subject_start; |
| 5760 while (limit > 0) { |
| 5761 pos = reinterpret_cast<const char*>( |
| 5762 memchr(pos, pattern, subject_end - pos)); |
| 5763 if (pos == NULL) return; |
| 5764 indices->Add(static_cast<int>(pos - subject_start)); |
| 5765 pos++; |
| 5766 limit--; |
| 5767 } |
| 5768 } |
| 5769 |
| 5770 |
| 5567 template <typename SubjectChar, typename PatternChar> | 5771 template <typename SubjectChar, typename PatternChar> |
| 5568 void FindStringIndices(Isolate* isolate, | 5772 void FindStringIndices(Isolate* isolate, |
| 5569 Vector<const SubjectChar> subject, | 5773 Vector<const SubjectChar> subject, |
| 5570 Vector<const PatternChar> pattern, | 5774 Vector<const PatternChar> pattern, |
| 5571 ZoneList<int>* indices, | 5775 ZoneList<int>* indices, |
| 5572 unsigned int limit) { | 5776 unsigned int limit) { |
| 5573 ASSERT(limit > 0); | 5777 ASSERT(limit > 0); |
| 5574 // Collect indices of pattern in subject, and the end-of-string index. | 5778 // Collect indices of pattern in subject. |
| 5575 // Stop after finding at most limit values. | 5779 // Stop after finding at most limit values. |
| 5576 StringSearch<PatternChar, SubjectChar> search(isolate, pattern); | |
| 5577 int pattern_length = pattern.length(); | 5780 int pattern_length = pattern.length(); |
| 5578 int index = 0; | 5781 int index = 0; |
| 5782 StringSearch<PatternChar, SubjectChar> search(isolate, pattern); |
| 5579 while (limit > 0) { | 5783 while (limit > 0) { |
| 5580 index = search.Search(subject, index); | 5784 index = search.Search(subject, index); |
| 5581 if (index < 0) return; | 5785 if (index < 0) return; |
| 5582 indices->Add(index); | 5786 indices->Add(index); |
| 5583 index += pattern_length; | 5787 index += pattern_length; |
| 5584 limit--; | 5788 limit--; |
| 5585 } | 5789 } |
| 5586 } | 5790 } |
| 5587 | 5791 |
| 5588 | 5792 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5611 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); | 5815 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); |
| 5612 ZoneList<int> indices(initial_capacity); | 5816 ZoneList<int> indices(initial_capacity); |
| 5613 if (!pattern->IsFlat()) FlattenString(pattern); | 5817 if (!pattern->IsFlat()) FlattenString(pattern); |
| 5614 | 5818 |
| 5615 // No allocation block. | 5819 // No allocation block. |
| 5616 { | 5820 { |
| 5617 AssertNoAllocation nogc; | 5821 AssertNoAllocation nogc; |
| 5618 if (subject->IsAsciiRepresentation()) { | 5822 if (subject->IsAsciiRepresentation()) { |
| 5619 Vector<const char> subject_vector = subject->ToAsciiVector(); | 5823 Vector<const char> subject_vector = subject->ToAsciiVector(); |
| 5620 if (pattern->IsAsciiRepresentation()) { | 5824 if (pattern->IsAsciiRepresentation()) { |
| 5621 FindStringIndices(isolate, | 5825 Vector<const char> pattern_vector = pattern->ToAsciiVector(); |
| 5622 subject_vector, | 5826 if (pattern_vector.length() == 1) { |
| 5623 pattern->ToAsciiVector(), | 5827 FindAsciiStringIndices(subject_vector, |
| 5624 &indices, | 5828 pattern_vector[0], |
| 5625 limit); | 5829 &indices, |
| 5830 limit); |
| 5831 } else { |
| 5832 FindStringIndices(isolate, |
| 5833 subject_vector, |
| 5834 pattern_vector, |
| 5835 &indices, |
| 5836 limit); |
| 5837 } |
| 5626 } else { | 5838 } else { |
| 5627 FindStringIndices(isolate, | 5839 FindStringIndices(isolate, |
| 5628 subject_vector, | 5840 subject_vector, |
| 5629 pattern->ToUC16Vector(), | 5841 pattern->ToUC16Vector(), |
| 5630 &indices, | 5842 &indices, |
| 5631 limit); | 5843 limit); |
| 5632 } | 5844 } |
| 5633 } else { | 5845 } else { |
| 5634 Vector<const uc16> subject_vector = subject->ToUC16Vector(); | 5846 Vector<const uc16> subject_vector = subject->ToUC16Vector(); |
| 5635 if (pattern->IsAsciiRepresentation()) { | 5847 if (pattern->IsAsciiRepresentation()) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 5666 FixedArray::cast(result->elements())->set(0, *subject); | 5878 FixedArray::cast(result->elements())->set(0, *subject); |
| 5667 return *result; | 5879 return *result; |
| 5668 } | 5880 } |
| 5669 | 5881 |
| 5670 Handle<FixedArray> elements(FixedArray::cast(result->elements())); | 5882 Handle<FixedArray> elements(FixedArray::cast(result->elements())); |
| 5671 int part_start = 0; | 5883 int part_start = 0; |
| 5672 for (int i = 0; i < part_count; i++) { | 5884 for (int i = 0; i < part_count; i++) { |
| 5673 HandleScope local_loop_handle; | 5885 HandleScope local_loop_handle; |
| 5674 int part_end = indices.at(i); | 5886 int part_end = indices.at(i); |
| 5675 Handle<String> substring = | 5887 Handle<String> substring = |
| 5676 isolate->factory()->NewSubString(subject, part_start, part_end); | 5888 isolate->factory()->NewProperSubString(subject, part_start, part_end); |
| 5677 elements->set(i, *substring); | 5889 elements->set(i, *substring); |
| 5678 part_start = part_end + pattern_length; | 5890 part_start = part_end + pattern_length; |
| 5679 } | 5891 } |
| 5680 | 5892 |
| 5681 return *result; | 5893 return *result; |
| 5682 } | 5894 } |
| 5683 | 5895 |
| 5684 | 5896 |
| 5685 // Copies ascii characters to the given fixed array looking up | 5897 // Copies ascii characters to the given fixed array looking up |
| 5686 // one-char strings in the cache. Gives up on the first char that is | 5898 // one-char strings in the cache. Gives up on the first char that is |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5799 RUNTIME_ASSERT(number->IsNumber()); | 6011 RUNTIME_ASSERT(number->IsNumber()); |
| 5800 | 6012 |
| 5801 return isolate->heap()->NumberToString(number, false); | 6013 return isolate->heap()->NumberToString(number, false); |
| 5802 } | 6014 } |
| 5803 | 6015 |
| 5804 | 6016 |
| 5805 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) { | 6017 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) { |
| 5806 NoHandleAllocation ha; | 6018 NoHandleAllocation ha; |
| 5807 ASSERT(args.length() == 1); | 6019 ASSERT(args.length() == 1); |
| 5808 | 6020 |
| 5809 CONVERT_DOUBLE_CHECKED(number, args[0]); | 6021 CONVERT_DOUBLE_ARG_CHECKED(number, 0); |
| 5810 | 6022 |
| 5811 // We do not include 0 so that we don't have to treat +0 / -0 cases. | 6023 // We do not include 0 so that we don't have to treat +0 / -0 cases. |
| 5812 if (number > 0 && number <= Smi::kMaxValue) { | 6024 if (number > 0 && number <= Smi::kMaxValue) { |
| 5813 return Smi::FromInt(static_cast<int>(number)); | 6025 return Smi::FromInt(static_cast<int>(number)); |
| 5814 } | 6026 } |
| 5815 return isolate->heap()->NumberFromDouble(DoubleToInteger(number)); | 6027 return isolate->heap()->NumberFromDouble(DoubleToInteger(number)); |
| 5816 } | 6028 } |
| 5817 | 6029 |
| 5818 | 6030 |
| 5819 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) { | 6031 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) { |
| 5820 NoHandleAllocation ha; | 6032 NoHandleAllocation ha; |
| 5821 ASSERT(args.length() == 1); | 6033 ASSERT(args.length() == 1); |
| 5822 | 6034 |
| 5823 CONVERT_DOUBLE_CHECKED(number, args[0]); | 6035 CONVERT_DOUBLE_ARG_CHECKED(number, 0); |
| 5824 | 6036 |
| 5825 // We do not include 0 so that we don't have to treat +0 / -0 cases. | 6037 // We do not include 0 so that we don't have to treat +0 / -0 cases. |
| 5826 if (number > 0 && number <= Smi::kMaxValue) { | 6038 if (number > 0 && number <= Smi::kMaxValue) { |
| 5827 return Smi::FromInt(static_cast<int>(number)); | 6039 return Smi::FromInt(static_cast<int>(number)); |
| 5828 } | 6040 } |
| 5829 | 6041 |
| 5830 double double_value = DoubleToInteger(number); | 6042 double double_value = DoubleToInteger(number); |
| 5831 // Map both -0 and +0 to +0. | 6043 // Map both -0 and +0 to +0. |
| 5832 if (double_value == 0) double_value = 0; | 6044 if (double_value == 0) double_value = 0; |
| 5833 | 6045 |
| 5834 return isolate->heap()->NumberFromDouble(double_value); | 6046 return isolate->heap()->NumberFromDouble(double_value); |
| 5835 } | 6047 } |
| 5836 | 6048 |
| 5837 | 6049 |
| 5838 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) { | 6050 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) { |
| 5839 NoHandleAllocation ha; | 6051 NoHandleAllocation ha; |
| 5840 ASSERT(args.length() == 1); | 6052 ASSERT(args.length() == 1); |
| 5841 | 6053 |
| 5842 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]); | 6054 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]); |
| 5843 return isolate->heap()->NumberFromUint32(number); | 6055 return isolate->heap()->NumberFromUint32(number); |
| 5844 } | 6056 } |
| 5845 | 6057 |
| 5846 | 6058 |
| 5847 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) { | 6059 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) { |
| 5848 NoHandleAllocation ha; | 6060 NoHandleAllocation ha; |
| 5849 ASSERT(args.length() == 1); | 6061 ASSERT(args.length() == 1); |
| 5850 | 6062 |
| 5851 CONVERT_DOUBLE_CHECKED(number, args[0]); | 6063 CONVERT_DOUBLE_ARG_CHECKED(number, 0); |
| 5852 | 6064 |
| 5853 // We do not include 0 so that we don't have to treat +0 / -0 cases. | 6065 // We do not include 0 so that we don't have to treat +0 / -0 cases. |
| 5854 if (number > 0 && number <= Smi::kMaxValue) { | 6066 if (number > 0 && number <= Smi::kMaxValue) { |
| 5855 return Smi::FromInt(static_cast<int>(number)); | 6067 return Smi::FromInt(static_cast<int>(number)); |
| 5856 } | 6068 } |
| 5857 return isolate->heap()->NumberFromInt32(DoubleToInt32(number)); | 6069 return isolate->heap()->NumberFromInt32(DoubleToInt32(number)); |
| 5858 } | 6070 } |
| 5859 | 6071 |
| 5860 | 6072 |
| 5861 // Converts a Number to a Smi, if possible. Returns NaN if the number is not | 6073 // Converts a Number to a Smi, if possible. Returns NaN if the number is not |
| (...skipping 21 matching lines...) Expand all Loading... |
| 5883 NoHandleAllocation ha; | 6095 NoHandleAllocation ha; |
| 5884 ASSERT(args.length() == 0); | 6096 ASSERT(args.length() == 0); |
| 5885 return isolate->heap()->AllocateHeapNumber(0); | 6097 return isolate->heap()->AllocateHeapNumber(0); |
| 5886 } | 6098 } |
| 5887 | 6099 |
| 5888 | 6100 |
| 5889 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) { | 6101 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) { |
| 5890 NoHandleAllocation ha; | 6102 NoHandleAllocation ha; |
| 5891 ASSERT(args.length() == 2); | 6103 ASSERT(args.length() == 2); |
| 5892 | 6104 |
| 5893 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6105 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 5894 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6106 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 5895 return isolate->heap()->NumberFromDouble(x + y); | 6107 return isolate->heap()->NumberFromDouble(x + y); |
| 5896 } | 6108 } |
| 5897 | 6109 |
| 5898 | 6110 |
| 5899 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) { | 6111 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) { |
| 5900 NoHandleAllocation ha; | 6112 NoHandleAllocation ha; |
| 5901 ASSERT(args.length() == 2); | 6113 ASSERT(args.length() == 2); |
| 5902 | 6114 |
| 5903 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6115 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 5904 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6116 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 5905 return isolate->heap()->NumberFromDouble(x - y); | 6117 return isolate->heap()->NumberFromDouble(x - y); |
| 5906 } | 6118 } |
| 5907 | 6119 |
| 5908 | 6120 |
| 5909 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) { | 6121 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) { |
| 5910 NoHandleAllocation ha; | 6122 NoHandleAllocation ha; |
| 5911 ASSERT(args.length() == 2); | 6123 ASSERT(args.length() == 2); |
| 5912 | 6124 |
| 5913 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6125 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 5914 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6126 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 5915 return isolate->heap()->NumberFromDouble(x * y); | 6127 return isolate->heap()->NumberFromDouble(x * y); |
| 5916 } | 6128 } |
| 5917 | 6129 |
| 5918 | 6130 |
| 5919 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) { | 6131 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) { |
| 5920 NoHandleAllocation ha; | 6132 NoHandleAllocation ha; |
| 5921 ASSERT(args.length() == 1); | 6133 ASSERT(args.length() == 1); |
| 5922 | 6134 |
| 5923 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6135 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 5924 return isolate->heap()->NumberFromDouble(-x); | 6136 return isolate->heap()->NumberFromDouble(-x); |
| 5925 } | 6137 } |
| 5926 | 6138 |
| 5927 | 6139 |
| 5928 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) { | 6140 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) { |
| 5929 NoHandleAllocation ha; | 6141 NoHandleAllocation ha; |
| 5930 ASSERT(args.length() == 0); | 6142 ASSERT(args.length() == 0); |
| 5931 | 6143 |
| 5932 return isolate->heap()->NumberFromDouble(9876543210.0); | 6144 return isolate->heap()->NumberFromDouble(9876543210.0); |
| 5933 } | 6145 } |
| 5934 | 6146 |
| 5935 | 6147 |
| 5936 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) { | 6148 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) { |
| 5937 NoHandleAllocation ha; | 6149 NoHandleAllocation ha; |
| 5938 ASSERT(args.length() == 2); | 6150 ASSERT(args.length() == 2); |
| 5939 | 6151 |
| 5940 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6152 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 5941 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6153 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 5942 return isolate->heap()->NumberFromDouble(x / y); | 6154 return isolate->heap()->NumberFromDouble(x / y); |
| 5943 } | 6155 } |
| 5944 | 6156 |
| 5945 | 6157 |
| 5946 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) { | 6158 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) { |
| 5947 NoHandleAllocation ha; | 6159 NoHandleAllocation ha; |
| 5948 ASSERT(args.length() == 2); | 6160 ASSERT(args.length() == 2); |
| 5949 | 6161 |
| 5950 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6162 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 5951 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6163 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 5952 | 6164 |
| 5953 x = modulo(x, y); | 6165 x = modulo(x, y); |
| 5954 // NumberFromDouble may return a Smi instead of a Number object | 6166 // NumberFromDouble may return a Smi instead of a Number object |
| 5955 return isolate->heap()->NumberFromDouble(x); | 6167 return isolate->heap()->NumberFromDouble(x); |
| 5956 } | 6168 } |
| 5957 | 6169 |
| 5958 | 6170 |
| 5959 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) { | 6171 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) { |
| 5960 NoHandleAllocation ha; | 6172 NoHandleAllocation ha; |
| 5961 ASSERT(args.length() == 2); | 6173 ASSERT(args.length() == 2); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6006 | 6218 |
| 6007 | 6219 |
| 6008 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { | 6220 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { |
| 6009 NoHandleAllocation ha; | 6221 NoHandleAllocation ha; |
| 6010 ASSERT(args.length() == 3); | 6222 ASSERT(args.length() == 3); |
| 6011 CONVERT_CHECKED(JSArray, array, args[0]); | 6223 CONVERT_CHECKED(JSArray, array, args[0]); |
| 6012 if (!args[1]->IsSmi()) { | 6224 if (!args[1]->IsSmi()) { |
| 6013 isolate->context()->mark_out_of_memory(); | 6225 isolate->context()->mark_out_of_memory(); |
| 6014 return Failure::OutOfMemoryException(); | 6226 return Failure::OutOfMemoryException(); |
| 6015 } | 6227 } |
| 6016 int array_length = Smi::cast(args[1])->value(); | 6228 int array_length = args.smi_at(1); |
| 6017 CONVERT_CHECKED(String, special, args[2]); | 6229 CONVERT_CHECKED(String, special, args[2]); |
| 6018 | 6230 |
| 6019 // This assumption is used by the slice encoding in one or two smis. | 6231 // This assumption is used by the slice encoding in one or two smis. |
| 6020 ASSERT(Smi::kMaxValue >= String::kMaxLength); | 6232 ASSERT(Smi::kMaxValue >= String::kMaxLength); |
| 6021 | 6233 |
| 6022 int special_length = special->length(); | 6234 int special_length = special->length(); |
| 6023 if (!array->HasFastElements()) { | 6235 if (!array->HasFastElements()) { |
| 6024 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); | 6236 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); |
| 6025 } | 6237 } |
| 6026 FixedArray* fixed_array = FixedArray::cast(array->elements()); | 6238 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6119 | 6331 |
| 6120 | 6332 |
| 6121 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { | 6333 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) { |
| 6122 NoHandleAllocation ha; | 6334 NoHandleAllocation ha; |
| 6123 ASSERT(args.length() == 3); | 6335 ASSERT(args.length() == 3); |
| 6124 CONVERT_CHECKED(JSArray, array, args[0]); | 6336 CONVERT_CHECKED(JSArray, array, args[0]); |
| 6125 if (!args[1]->IsSmi()) { | 6337 if (!args[1]->IsSmi()) { |
| 6126 isolate->context()->mark_out_of_memory(); | 6338 isolate->context()->mark_out_of_memory(); |
| 6127 return Failure::OutOfMemoryException(); | 6339 return Failure::OutOfMemoryException(); |
| 6128 } | 6340 } |
| 6129 int array_length = Smi::cast(args[1])->value(); | 6341 int array_length = args.smi_at(1); |
| 6130 CONVERT_CHECKED(String, separator, args[2]); | 6342 CONVERT_CHECKED(String, separator, args[2]); |
| 6131 | 6343 |
| 6132 if (!array->HasFastElements()) { | 6344 if (!array->HasFastElements()) { |
| 6133 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); | 6345 return isolate->Throw(isolate->heap()->illegal_argument_symbol()); |
| 6134 } | 6346 } |
| 6135 FixedArray* fixed_array = FixedArray::cast(array->elements()); | 6347 FixedArray* fixed_array = FixedArray::cast(array->elements()); |
| 6136 if (fixed_array->length() < array_length) { | 6348 if (fixed_array->length() < array_length) { |
| 6137 array_length = fixed_array->length(); | 6349 array_length = fixed_array->length(); |
| 6138 } | 6350 } |
| 6139 | 6351 |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6397 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); | 6609 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]); |
| 6398 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); | 6610 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]); |
| 6399 return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f)); | 6611 return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f)); |
| 6400 } | 6612 } |
| 6401 | 6613 |
| 6402 | 6614 |
| 6403 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) { | 6615 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) { |
| 6404 NoHandleAllocation ha; | 6616 NoHandleAllocation ha; |
| 6405 ASSERT(args.length() == 2); | 6617 ASSERT(args.length() == 2); |
| 6406 | 6618 |
| 6407 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6619 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6408 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6620 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 6409 if (isnan(x)) return Smi::FromInt(NOT_EQUAL); | 6621 if (isnan(x)) return Smi::FromInt(NOT_EQUAL); |
| 6410 if (isnan(y)) return Smi::FromInt(NOT_EQUAL); | 6622 if (isnan(y)) return Smi::FromInt(NOT_EQUAL); |
| 6411 if (x == y) return Smi::FromInt(EQUAL); | 6623 if (x == y) return Smi::FromInt(EQUAL); |
| 6412 Object* result; | 6624 Object* result; |
| 6413 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { | 6625 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) { |
| 6414 result = Smi::FromInt(EQUAL); | 6626 result = Smi::FromInt(EQUAL); |
| 6415 } else { | 6627 } else { |
| 6416 result = Smi::FromInt(NOT_EQUAL); | 6628 result = Smi::FromInt(NOT_EQUAL); |
| 6417 } | 6629 } |
| 6418 return result; | 6630 return result; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6434 STATIC_CHECK(EQUAL == 0); | 6646 STATIC_CHECK(EQUAL == 0); |
| 6435 STATIC_CHECK(NOT_EQUAL == 1); | 6647 STATIC_CHECK(NOT_EQUAL == 1); |
| 6436 return Smi::FromInt(not_equal); | 6648 return Smi::FromInt(not_equal); |
| 6437 } | 6649 } |
| 6438 | 6650 |
| 6439 | 6651 |
| 6440 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) { | 6652 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) { |
| 6441 NoHandleAllocation ha; | 6653 NoHandleAllocation ha; |
| 6442 ASSERT(args.length() == 3); | 6654 ASSERT(args.length() == 3); |
| 6443 | 6655 |
| 6444 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6656 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6445 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6657 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 6446 if (isnan(x) || isnan(y)) return args[2]; | 6658 if (isnan(x) || isnan(y)) return args[2]; |
| 6447 if (x == y) return Smi::FromInt(EQUAL); | 6659 if (x == y) return Smi::FromInt(EQUAL); |
| 6448 if (isless(x, y)) return Smi::FromInt(LESS); | 6660 if (isless(x, y)) return Smi::FromInt(LESS); |
| 6449 return Smi::FromInt(GREATER); | 6661 return Smi::FromInt(GREATER); |
| 6450 } | 6662 } |
| 6451 | 6663 |
| 6452 | 6664 |
| 6453 // Compare two Smis as if they were converted to strings and then | 6665 // Compare two Smis as if they were converted to strings and then |
| 6454 // compared lexicographically. | 6666 // compared lexicographically. |
| 6455 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) { | 6667 RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) { |
| 6456 NoHandleAllocation ha; | 6668 NoHandleAllocation ha; |
| 6457 ASSERT(args.length() == 2); | 6669 ASSERT(args.length() == 2); |
| 6458 | 6670 |
| 6459 // Extract the integer values from the Smis. | 6671 // Extract the integer values from the Smis. |
| 6460 CONVERT_CHECKED(Smi, x, args[0]); | 6672 CONVERT_CHECKED(Smi, x, args[0]); |
| 6461 CONVERT_CHECKED(Smi, y, args[1]); | 6673 CONVERT_CHECKED(Smi, y, args[1]); |
| 6462 int x_value = x->value(); | 6674 int x_value = x->value(); |
| 6463 int y_value = y->value(); | 6675 int y_value = y->value(); |
| 6464 | 6676 |
| 6465 // If the integers are equal so are the string representations. | 6677 // If the integers are equal so are the string representations. |
| 6466 if (x_value == y_value) return Smi::FromInt(EQUAL); | 6678 if (x_value == y_value) return Smi::FromInt(EQUAL); |
| 6467 | 6679 |
| 6468 // If one of the integers are zero the normal integer order is the | 6680 // If one of the integers is zero the normal integer order is the |
| 6469 // same as the lexicographic order of the string representations. | 6681 // same as the lexicographic order of the string representations. |
| 6470 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); | 6682 if (x_value == 0 || y_value == 0) |
| 6683 return Smi::FromInt(x_value < y_value ? LESS : GREATER); |
| 6471 | 6684 |
| 6472 // If only one of the integers is negative the negative number is | 6685 // If only one of the integers is negative the negative number is |
| 6473 // smallest because the char code of '-' is less than the char code | 6686 // smallest because the char code of '-' is less than the char code |
| 6474 // of any digit. Otherwise, we make both values positive. | 6687 // of any digit. Otherwise, we make both values positive. |
| 6688 |
| 6689 // Use unsigned values otherwise the logic is incorrect for -MIN_INT on |
| 6690 // architectures using 32-bit Smis. |
| 6691 uint32_t x_scaled = x_value; |
| 6692 uint32_t y_scaled = y_value; |
| 6475 if (x_value < 0 || y_value < 0) { | 6693 if (x_value < 0 || y_value < 0) { |
| 6476 if (y_value >= 0) return Smi::FromInt(LESS); | 6694 if (y_value >= 0) return Smi::FromInt(LESS); |
| 6477 if (x_value >= 0) return Smi::FromInt(GREATER); | 6695 if (x_value >= 0) return Smi::FromInt(GREATER); |
| 6478 x_value = -x_value; | 6696 x_scaled = -x_value; |
| 6479 y_value = -y_value; | 6697 y_scaled = -y_value; |
| 6480 } | 6698 } |
| 6481 | 6699 |
| 6482 // Arrays for the individual characters of the two Smis. Smis are | 6700 static const uint32_t kPowersOf10[] = { |
| 6483 // 31 bit integers and 10 decimal digits are therefore enough. | 6701 1, 10, 100, 1000, 10*1000, 100*1000, |
| 6484 // TODO(isolates): maybe we should simply allocate 20 bytes on the stack. | 6702 1000*1000, 10*1000*1000, 100*1000*1000, |
| 6485 int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms(); | 6703 1000*1000*1000 |
| 6486 int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms(); | 6704 }; |
| 6487 | 6705 |
| 6706 // If the integers have the same number of decimal digits they can be |
| 6707 // compared directly as the numeric order is the same as the |
| 6708 // lexicographic order. If one integer has fewer digits, it is scaled |
| 6709 // by some power of 10 to have the same number of digits as the longer |
| 6710 // integer. If the scaled integers are equal it means the shorter |
| 6711 // integer comes first in the lexicographic order. |
| 6488 | 6712 |
| 6489 // Convert the integers to arrays of their decimal digits. | 6713 // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 |
| 6490 int x_index = 0; | 6714 int x_log2 = IntegerLog2(x_scaled); |
| 6491 int y_index = 0; | 6715 int x_log10 = ((x_log2 + 1) * 1233) >> 12; |
| 6492 while (x_value > 0) { | 6716 x_log10 -= x_scaled < kPowersOf10[x_log10]; |
| 6493 x_elms[x_index++] = x_value % 10; | 6717 |
| 6494 x_value /= 10; | 6718 int y_log2 = IntegerLog2(y_scaled); |
| 6495 } | 6719 int y_log10 = ((y_log2 + 1) * 1233) >> 12; |
| 6496 while (y_value > 0) { | 6720 y_log10 -= y_scaled < kPowersOf10[y_log10]; |
| 6497 y_elms[y_index++] = y_value % 10; | 6721 |
| 6498 y_value /= 10; | 6722 int tie = EQUAL; |
| 6723 |
| 6724 if (x_log10 < y_log10) { |
| 6725 // X has fewer digits. We would like to simply scale up X but that |
| 6726 // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would |
| 6727 // be scaled up to 9_000_000_000. So we scale up by the next |
| 6728 // smallest power and scale down Y to drop one digit. It is OK to |
| 6729 // drop one digit from the longer integer since the final digit is |
| 6730 // past the length of the shorter integer. |
| 6731 x_scaled *= kPowersOf10[y_log10 - x_log10 - 1]; |
| 6732 y_scaled /= 10; |
| 6733 tie = LESS; |
| 6734 } else if (y_log10 < x_log10) { |
| 6735 y_scaled *= kPowersOf10[x_log10 - y_log10 - 1]; |
| 6736 x_scaled /= 10; |
| 6737 tie = GREATER; |
| 6499 } | 6738 } |
| 6500 | 6739 |
| 6501 // Loop through the arrays of decimal digits finding the first place | 6740 if (x_scaled < y_scaled) return Smi::FromInt(LESS); |
| 6502 // where they differ. | 6741 if (x_scaled > y_scaled) return Smi::FromInt(GREATER); |
| 6503 while (--x_index >= 0 && --y_index >= 0) { | 6742 return Smi::FromInt(tie); |
| 6504 int diff = x_elms[x_index] - y_elms[y_index]; | |
| 6505 if (diff != 0) return Smi::FromInt(diff); | |
| 6506 } | |
| 6507 | |
| 6508 // If one array is a suffix of the other array, the longest array is | |
| 6509 // the representation of the largest of the Smis in the | |
| 6510 // lexicographic ordering. | |
| 6511 return Smi::FromInt(x_index - y_index); | |
| 6512 } | 6743 } |
| 6513 | 6744 |
| 6514 | 6745 |
| 6515 static Object* StringInputBufferCompare(RuntimeState* state, | 6746 static Object* StringInputBufferCompare(RuntimeState* state, |
| 6516 String* x, | 6747 String* x, |
| 6517 String* y) { | 6748 String* y) { |
| 6518 StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx(); | 6749 StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx(); |
| 6519 StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy(); | 6750 StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy(); |
| 6520 bufx.Reset(x); | 6751 bufx.Reset(x); |
| 6521 bufy.Reset(y); | 6752 bufy.Reset(y); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6608 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) | 6839 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) |
| 6609 : StringInputBufferCompare(isolate->runtime_state(), x, y); | 6840 : StringInputBufferCompare(isolate->runtime_state(), x, y); |
| 6610 } | 6841 } |
| 6611 | 6842 |
| 6612 | 6843 |
| 6613 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) { | 6844 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) { |
| 6614 NoHandleAllocation ha; | 6845 NoHandleAllocation ha; |
| 6615 ASSERT(args.length() == 1); | 6846 ASSERT(args.length() == 1); |
| 6616 isolate->counters()->math_acos()->Increment(); | 6847 isolate->counters()->math_acos()->Increment(); |
| 6617 | 6848 |
| 6618 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6849 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6619 return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x); | 6850 return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x); |
| 6620 } | 6851 } |
| 6621 | 6852 |
| 6622 | 6853 |
| 6623 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) { | 6854 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) { |
| 6624 NoHandleAllocation ha; | 6855 NoHandleAllocation ha; |
| 6625 ASSERT(args.length() == 1); | 6856 ASSERT(args.length() == 1); |
| 6626 isolate->counters()->math_asin()->Increment(); | 6857 isolate->counters()->math_asin()->Increment(); |
| 6627 | 6858 |
| 6628 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6859 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6629 return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x); | 6860 return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x); |
| 6630 } | 6861 } |
| 6631 | 6862 |
| 6632 | 6863 |
| 6633 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) { | 6864 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) { |
| 6634 NoHandleAllocation ha; | 6865 NoHandleAllocation ha; |
| 6635 ASSERT(args.length() == 1); | 6866 ASSERT(args.length() == 1); |
| 6636 isolate->counters()->math_atan()->Increment(); | 6867 isolate->counters()->math_atan()->Increment(); |
| 6637 | 6868 |
| 6638 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6869 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6639 return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x); | 6870 return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x); |
| 6640 } | 6871 } |
| 6641 | 6872 |
| 6642 | 6873 |
| 6643 static const double kPiDividedBy4 = 0.78539816339744830962; | 6874 static const double kPiDividedBy4 = 0.78539816339744830962; |
| 6644 | 6875 |
| 6645 | 6876 |
| 6646 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) { | 6877 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) { |
| 6647 NoHandleAllocation ha; | 6878 NoHandleAllocation ha; |
| 6648 ASSERT(args.length() == 2); | 6879 ASSERT(args.length() == 2); |
| 6649 isolate->counters()->math_atan2()->Increment(); | 6880 isolate->counters()->math_atan2()->Increment(); |
| 6650 | 6881 |
| 6651 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6882 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6652 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6883 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 6653 double result; | 6884 double result; |
| 6654 if (isinf(x) && isinf(y)) { | 6885 if (isinf(x) && isinf(y)) { |
| 6655 // Make sure that the result in case of two infinite arguments | 6886 // Make sure that the result in case of two infinite arguments |
| 6656 // is a multiple of Pi / 4. The sign of the result is determined | 6887 // is a multiple of Pi / 4. The sign of the result is determined |
| 6657 // by the first argument (x) and the sign of the second argument | 6888 // by the first argument (x) and the sign of the second argument |
| 6658 // determines the multiplier: one or three. | 6889 // determines the multiplier: one or three. |
| 6659 int multiplier = (x < 0) ? -1 : 1; | 6890 int multiplier = (x < 0) ? -1 : 1; |
| 6660 if (y < 0) multiplier *= 3; | 6891 if (y < 0) multiplier *= 3; |
| 6661 result = multiplier * kPiDividedBy4; | 6892 result = multiplier * kPiDividedBy4; |
| 6662 } else { | 6893 } else { |
| 6663 result = atan2(x, y); | 6894 result = atan2(x, y); |
| 6664 } | 6895 } |
| 6665 return isolate->heap()->AllocateHeapNumber(result); | 6896 return isolate->heap()->AllocateHeapNumber(result); |
| 6666 } | 6897 } |
| 6667 | 6898 |
| 6668 | 6899 |
| 6669 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) { | 6900 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) { |
| 6670 NoHandleAllocation ha; | 6901 NoHandleAllocation ha; |
| 6671 ASSERT(args.length() == 1); | 6902 ASSERT(args.length() == 1); |
| 6672 isolate->counters()->math_ceil()->Increment(); | 6903 isolate->counters()->math_ceil()->Increment(); |
| 6673 | 6904 |
| 6674 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6905 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6675 return isolate->heap()->NumberFromDouble(ceiling(x)); | 6906 return isolate->heap()->NumberFromDouble(ceiling(x)); |
| 6676 } | 6907 } |
| 6677 | 6908 |
| 6678 | 6909 |
| 6679 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) { | 6910 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) { |
| 6680 NoHandleAllocation ha; | 6911 NoHandleAllocation ha; |
| 6681 ASSERT(args.length() == 1); | 6912 ASSERT(args.length() == 1); |
| 6682 isolate->counters()->math_cos()->Increment(); | 6913 isolate->counters()->math_cos()->Increment(); |
| 6683 | 6914 |
| 6684 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6915 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6685 return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x); | 6916 return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x); |
| 6686 } | 6917 } |
| 6687 | 6918 |
| 6688 | 6919 |
| 6689 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) { | 6920 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) { |
| 6690 NoHandleAllocation ha; | 6921 NoHandleAllocation ha; |
| 6691 ASSERT(args.length() == 1); | 6922 ASSERT(args.length() == 1); |
| 6692 isolate->counters()->math_exp()->Increment(); | 6923 isolate->counters()->math_exp()->Increment(); |
| 6693 | 6924 |
| 6694 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6925 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6695 return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x); | 6926 return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x); |
| 6696 } | 6927 } |
| 6697 | 6928 |
| 6698 | 6929 |
| 6699 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) { | 6930 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) { |
| 6700 NoHandleAllocation ha; | 6931 NoHandleAllocation ha; |
| 6701 ASSERT(args.length() == 1); | 6932 ASSERT(args.length() == 1); |
| 6702 isolate->counters()->math_floor()->Increment(); | 6933 isolate->counters()->math_floor()->Increment(); |
| 6703 | 6934 |
| 6704 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6935 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6705 return isolate->heap()->NumberFromDouble(floor(x)); | 6936 return isolate->heap()->NumberFromDouble(floor(x)); |
| 6706 } | 6937 } |
| 6707 | 6938 |
| 6708 | 6939 |
| 6709 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) { | 6940 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) { |
| 6710 NoHandleAllocation ha; | 6941 NoHandleAllocation ha; |
| 6711 ASSERT(args.length() == 1); | 6942 ASSERT(args.length() == 1); |
| 6712 isolate->counters()->math_log()->Increment(); | 6943 isolate->counters()->math_log()->Increment(); |
| 6713 | 6944 |
| 6714 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6945 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6715 return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x); | 6946 return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x); |
| 6716 } | 6947 } |
| 6717 | 6948 |
| 6718 | 6949 |
| 6719 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) { | 6950 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) { |
| 6720 NoHandleAllocation ha; | 6951 NoHandleAllocation ha; |
| 6721 ASSERT(args.length() == 2); | 6952 ASSERT(args.length() == 2); |
| 6722 isolate->counters()->math_pow()->Increment(); | 6953 isolate->counters()->math_pow()->Increment(); |
| 6723 | 6954 |
| 6724 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6955 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6725 | 6956 |
| 6726 // If the second argument is a smi, it is much faster to call the | 6957 // If the second argument is a smi, it is much faster to call the |
| 6727 // custom powi() function than the generic pow(). | 6958 // custom powi() function than the generic pow(). |
| 6728 if (args[1]->IsSmi()) { | 6959 if (args[1]->IsSmi()) { |
| 6729 int y = Smi::cast(args[1])->value(); | 6960 int y = args.smi_at(1); |
| 6730 return isolate->heap()->NumberFromDouble(power_double_int(x, y)); | 6961 return isolate->heap()->NumberFromDouble(power_double_int(x, y)); |
| 6731 } | 6962 } |
| 6732 | 6963 |
| 6733 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6964 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 6734 return isolate->heap()->AllocateHeapNumber(power_double_double(x, y)); | 6965 return isolate->heap()->AllocateHeapNumber(power_double_double(x, y)); |
| 6735 } | 6966 } |
| 6736 | 6967 |
| 6737 // Fast version of Math.pow if we know that y is not an integer and | 6968 // Fast version of Math.pow if we know that y is not an integer and |
| 6738 // y is not -0.5 or 0.5. Used as slowcase from codegen. | 6969 // y is not -0.5 or 0.5. Used as slowcase from codegen. |
| 6739 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) { | 6970 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) { |
| 6740 NoHandleAllocation ha; | 6971 NoHandleAllocation ha; |
| 6741 ASSERT(args.length() == 2); | 6972 ASSERT(args.length() == 2); |
| 6742 CONVERT_DOUBLE_CHECKED(x, args[0]); | 6973 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6743 CONVERT_DOUBLE_CHECKED(y, args[1]); | 6974 CONVERT_DOUBLE_ARG_CHECKED(y, 1); |
| 6744 if (y == 0) { | 6975 if (y == 0) { |
| 6745 return Smi::FromInt(1); | 6976 return Smi::FromInt(1); |
| 6746 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { | 6977 } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) { |
| 6747 return isolate->heap()->nan_value(); | 6978 return isolate->heap()->nan_value(); |
| 6748 } else { | 6979 } else { |
| 6749 return isolate->heap()->AllocateHeapNumber(pow(x, y)); | 6980 return isolate->heap()->AllocateHeapNumber(pow(x, y)); |
| 6750 } | 6981 } |
| 6751 } | 6982 } |
| 6752 | 6983 |
| 6753 | 6984 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6792 // Do not call NumberFromDouble() to avoid extra checks. | 7023 // Do not call NumberFromDouble() to avoid extra checks. |
| 6793 return isolate->heap()->AllocateHeapNumber(floor(value + 0.5)); | 7024 return isolate->heap()->AllocateHeapNumber(floor(value + 0.5)); |
| 6794 } | 7025 } |
| 6795 | 7026 |
| 6796 | 7027 |
| 6797 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) { | 7028 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) { |
| 6798 NoHandleAllocation ha; | 7029 NoHandleAllocation ha; |
| 6799 ASSERT(args.length() == 1); | 7030 ASSERT(args.length() == 1); |
| 6800 isolate->counters()->math_sin()->Increment(); | 7031 isolate->counters()->math_sin()->Increment(); |
| 6801 | 7032 |
| 6802 CONVERT_DOUBLE_CHECKED(x, args[0]); | 7033 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6803 return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x); | 7034 return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x); |
| 6804 } | 7035 } |
| 6805 | 7036 |
| 6806 | 7037 |
| 6807 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) { | 7038 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) { |
| 6808 NoHandleAllocation ha; | 7039 NoHandleAllocation ha; |
| 6809 ASSERT(args.length() == 1); | 7040 ASSERT(args.length() == 1); |
| 6810 isolate->counters()->math_sqrt()->Increment(); | 7041 isolate->counters()->math_sqrt()->Increment(); |
| 6811 | 7042 |
| 6812 CONVERT_DOUBLE_CHECKED(x, args[0]); | 7043 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6813 return isolate->heap()->AllocateHeapNumber(sqrt(x)); | 7044 return isolate->heap()->AllocateHeapNumber(sqrt(x)); |
| 6814 } | 7045 } |
| 6815 | 7046 |
| 6816 | 7047 |
| 6817 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) { | 7048 RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) { |
| 6818 NoHandleAllocation ha; | 7049 NoHandleAllocation ha; |
| 6819 ASSERT(args.length() == 1); | 7050 ASSERT(args.length() == 1); |
| 6820 isolate->counters()->math_tan()->Increment(); | 7051 isolate->counters()->math_tan()->Increment(); |
| 6821 | 7052 |
| 6822 CONVERT_DOUBLE_CHECKED(x, args[0]); | 7053 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 6823 return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x); | 7054 return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x); |
| 6824 } | 7055 } |
| 6825 | 7056 |
| 6826 | 7057 |
| 6827 static int MakeDay(int year, int month, int day) { | 7058 static int MakeDay(int year, int month, int day) { |
| 6828 static const int day_from_month[] = {0, 31, 59, 90, 120, 151, | 7059 static const int day_from_month[] = {0, 31, 59, 90, 120, 151, |
| 6829 181, 212, 243, 273, 304, 334}; | 7060 181, 212, 243, 273, 304, 334}; |
| 6830 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, | 7061 static const int day_from_month_leap[] = {0, 31, 60, 91, 121, 152, |
| 6831 182, 213, 244, 274, 305, 335}; | 7062 182, 213, 244, 274, 305, 335}; |
| 6832 | 7063 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6866 } | 7097 } |
| 6867 | 7098 |
| 6868 return day_from_year + day_from_month_leap[month] + day - 1; | 7099 return day_from_year + day_from_month_leap[month] + day - 1; |
| 6869 } | 7100 } |
| 6870 | 7101 |
| 6871 | 7102 |
| 6872 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) { | 7103 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) { |
| 6873 NoHandleAllocation ha; | 7104 NoHandleAllocation ha; |
| 6874 ASSERT(args.length() == 3); | 7105 ASSERT(args.length() == 3); |
| 6875 | 7106 |
| 6876 CONVERT_SMI_CHECKED(year, args[0]); | 7107 CONVERT_SMI_ARG_CHECKED(year, 0); |
| 6877 CONVERT_SMI_CHECKED(month, args[1]); | 7108 CONVERT_SMI_ARG_CHECKED(month, 1); |
| 6878 CONVERT_SMI_CHECKED(date, args[2]); | 7109 CONVERT_SMI_ARG_CHECKED(date, 2); |
| 6879 | 7110 |
| 6880 return Smi::FromInt(MakeDay(year, month, date)); | 7111 return Smi::FromInt(MakeDay(year, month, date)); |
| 6881 } | 7112 } |
| 6882 | 7113 |
| 6883 | 7114 |
| 6884 static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1}; | 7115 static const int kDays4Years[] = {0, 365, 2 * 365, 3 * 365 + 1}; |
| 6885 static const int kDaysIn4Years = 4 * 365 + 1; | 7116 static const int kDaysIn4Years = 4 * 365 + 1; |
| 6886 static const int kDaysIn100Years = 25 * kDaysIn4Years - 1; | 7117 static const int kDaysIn100Years = 25 * kDaysIn4Years - 1; |
| 6887 static const int kDaysIn400Years = 4 * kDaysIn100Years + 1; | 7118 static const int kDaysIn400Years = 4 * kDaysIn100Years + 1; |
| 6888 static const int kDays1970to2000 = 30 * 365 + 7; | 7119 static const int kDays1970to2000 = 30 * 365 + 7; |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7165 } else { | 7396 } else { |
| 7166 DateYMDFromTimeSlow(date, year, month, day); | 7397 DateYMDFromTimeSlow(date, year, month, day); |
| 7167 } | 7398 } |
| 7168 } | 7399 } |
| 7169 | 7400 |
| 7170 | 7401 |
| 7171 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateYMDFromTime) { | 7402 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateYMDFromTime) { |
| 7172 NoHandleAllocation ha; | 7403 NoHandleAllocation ha; |
| 7173 ASSERT(args.length() == 2); | 7404 ASSERT(args.length() == 2); |
| 7174 | 7405 |
| 7175 CONVERT_DOUBLE_CHECKED(t, args[0]); | 7406 CONVERT_DOUBLE_ARG_CHECKED(t, 0); |
| 7176 CONVERT_CHECKED(JSArray, res_array, args[1]); | 7407 CONVERT_CHECKED(JSArray, res_array, args[1]); |
| 7177 | 7408 |
| 7178 int year, month, day; | 7409 int year, month, day; |
| 7179 DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day); | 7410 DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day); |
| 7180 | 7411 |
| 7181 RUNTIME_ASSERT(res_array->elements()->map() == | 7412 RUNTIME_ASSERT(res_array->elements()->map() == |
| 7182 isolate->heap()->fixed_array_map()); | 7413 isolate->heap()->fixed_array_map()); |
| 7183 FixedArray* elms = FixedArray::cast(res_array->elements()); | 7414 FixedArray* elms = FixedArray::cast(res_array->elements()); |
| 7184 RUNTIME_ASSERT(elms->length() == 3); | 7415 RUNTIME_ASSERT(elms->length() == 3); |
| 7185 | 7416 |
| 7186 elms->set(0, Smi::FromInt(year)); | 7417 elms->set(0, Smi::FromInt(year)); |
| 7187 elms->set(1, Smi::FromInt(month)); | 7418 elms->set(1, Smi::FromInt(month)); |
| 7188 elms->set(2, Smi::FromInt(day)); | 7419 elms->set(2, Smi::FromInt(day)); |
| 7189 | 7420 |
| 7190 return isolate->heap()->undefined_value(); | 7421 return isolate->heap()->undefined_value(); |
| 7191 } | 7422 } |
| 7192 | 7423 |
| 7193 | 7424 |
| 7194 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) { | 7425 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) { |
| 7426 HandleScope scope(isolate); |
| 7427 ASSERT(args.length() == 3); |
| 7428 |
| 7429 Handle<JSFunction> callee = args.at<JSFunction>(0); |
| 7430 Object** parameters = reinterpret_cast<Object**>(args[1]); |
| 7431 const int argument_count = Smi::cast(args[2])->value(); |
| 7432 |
| 7433 Handle<JSObject> result = |
| 7434 isolate->factory()->NewArgumentsObject(callee, argument_count); |
| 7435 // Allocate the elements if needed. |
| 7436 int parameter_count = callee->shared()->formal_parameter_count(); |
| 7437 if (argument_count > 0) { |
| 7438 if (parameter_count > 0) { |
| 7439 int mapped_count = Min(argument_count, parameter_count); |
| 7440 Handle<FixedArray> parameter_map = |
| 7441 isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); |
| 7442 parameter_map->set_map( |
| 7443 isolate->heap()->non_strict_arguments_elements_map()); |
| 7444 |
| 7445 Handle<Map> old_map(result->map()); |
| 7446 Handle<Map> new_map = |
| 7447 isolate->factory()->CopyMapDropTransitions(old_map); |
| 7448 new_map->set_elements_kind(JSObject::NON_STRICT_ARGUMENTS_ELEMENTS); |
| 7449 |
| 7450 result->set_map(*new_map); |
| 7451 result->set_elements(*parameter_map); |
| 7452 |
| 7453 // Store the context and the arguments array at the beginning of the |
| 7454 // parameter map. |
| 7455 Handle<Context> context(isolate->context()); |
| 7456 Handle<FixedArray> arguments = |
| 7457 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
| 7458 parameter_map->set(0, *context); |
| 7459 parameter_map->set(1, *arguments); |
| 7460 |
| 7461 // Loop over the actual parameters backwards. |
| 7462 int index = argument_count - 1; |
| 7463 while (index >= mapped_count) { |
| 7464 // These go directly in the arguments array and have no |
| 7465 // corresponding slot in the parameter map. |
| 7466 arguments->set(index, *(parameters - index - 1)); |
| 7467 --index; |
| 7468 } |
| 7469 |
| 7470 ScopeInfo<> scope_info(callee->shared()->scope_info()); |
| 7471 while (index >= 0) { |
| 7472 // Detect duplicate names to the right in the parameter list. |
| 7473 Handle<String> name = scope_info.parameter_name(index); |
| 7474 int context_slot_count = scope_info.number_of_context_slots(); |
| 7475 bool duplicate = false; |
| 7476 for (int j = index + 1; j < parameter_count; ++j) { |
| 7477 if (scope_info.parameter_name(j).is_identical_to(name)) { |
| 7478 duplicate = true; |
| 7479 break; |
| 7480 } |
| 7481 } |
| 7482 |
| 7483 if (duplicate) { |
| 7484 // This goes directly in the arguments array with a hole in the |
| 7485 // parameter map. |
| 7486 arguments->set(index, *(parameters - index - 1)); |
| 7487 parameter_map->set_the_hole(index + 2); |
| 7488 } else { |
| 7489 // The context index goes in the parameter map with a hole in the |
| 7490 // arguments array. |
| 7491 int context_index = -1; |
| 7492 for (int j = Context::MIN_CONTEXT_SLOTS; |
| 7493 j < context_slot_count; |
| 7494 ++j) { |
| 7495 if (scope_info.context_slot_name(j).is_identical_to(name)) { |
| 7496 context_index = j; |
| 7497 break; |
| 7498 } |
| 7499 } |
| 7500 ASSERT(context_index >= 0); |
| 7501 arguments->set_the_hole(index); |
| 7502 parameter_map->set(index + 2, Smi::FromInt(context_index)); |
| 7503 } |
| 7504 |
| 7505 --index; |
| 7506 } |
| 7507 } else { |
| 7508 // If there is no aliasing, the arguments object elements are not |
| 7509 // special in any way. |
| 7510 Handle<FixedArray> elements = |
| 7511 isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
| 7512 result->set_elements(*elements); |
| 7513 for (int i = 0; i < argument_count; ++i) { |
| 7514 elements->set(i, *(parameters - i - 1)); |
| 7515 } |
| 7516 } |
| 7517 } |
| 7518 return *result; |
| 7519 } |
| 7520 |
| 7521 |
| 7522 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) { |
| 7195 NoHandleAllocation ha; | 7523 NoHandleAllocation ha; |
| 7196 ASSERT(args.length() == 3); | 7524 ASSERT(args.length() == 3); |
| 7197 | 7525 |
| 7198 JSFunction* callee = JSFunction::cast(args[0]); | 7526 JSFunction* callee = JSFunction::cast(args[0]); |
| 7199 Object** parameters = reinterpret_cast<Object**>(args[1]); | 7527 Object** parameters = reinterpret_cast<Object**>(args[1]); |
| 7200 const int length = Smi::cast(args[2])->value(); | 7528 const int length = args.smi_at(2); |
| 7201 | 7529 |
| 7202 Object* result; | 7530 Object* result; |
| 7203 { MaybeObject* maybe_result = | 7531 { MaybeObject* maybe_result = |
| 7204 isolate->heap()->AllocateArgumentsObject(callee, length); | 7532 isolate->heap()->AllocateArgumentsObject(callee, length); |
| 7205 if (!maybe_result->ToObject(&result)) return maybe_result; | 7533 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 7206 } | 7534 } |
| 7207 // Allocate the elements if needed. | 7535 // Allocate the elements if needed. |
| 7208 if (length > 0) { | 7536 if (length > 0) { |
| 7209 // Allocate the fixed array. | 7537 // Allocate the fixed array. |
| 7210 Object* obj; | 7538 Object* obj; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 7227 } | 7555 } |
| 7228 | 7556 |
| 7229 | 7557 |
| 7230 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) { | 7558 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) { |
| 7231 HandleScope scope(isolate); | 7559 HandleScope scope(isolate); |
| 7232 ASSERT(args.length() == 3); | 7560 ASSERT(args.length() == 3); |
| 7233 CONVERT_ARG_CHECKED(Context, context, 0); | 7561 CONVERT_ARG_CHECKED(Context, context, 0); |
| 7234 CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1); | 7562 CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1); |
| 7235 CONVERT_BOOLEAN_CHECKED(pretenure, args[2]); | 7563 CONVERT_BOOLEAN_CHECKED(pretenure, args[2]); |
| 7236 | 7564 |
| 7237 // Allocate global closures in old space and allocate local closures | 7565 // The caller ensures that we pretenure closures that are assigned |
| 7238 // in new space. Additionally pretenure closures that are assigned | |
| 7239 // directly to properties. | 7566 // directly to properties. |
| 7240 pretenure = pretenure || (context->global_context() == *context); | |
| 7241 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; | 7567 PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED; |
| 7242 Handle<JSFunction> result = | 7568 Handle<JSFunction> result = |
| 7243 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, | 7569 isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, |
| 7244 context, | 7570 context, |
| 7245 pretenure_flag); | 7571 pretenure_flag); |
| 7246 return *result; | 7572 return *result; |
| 7247 } | 7573 } |
| 7248 | 7574 |
| 7249 | 7575 |
| 7250 static SmartPointer<Object**> GetNonBoundArguments(int bound_argc, | 7576 static SmartPointer<Object**> GetNonBoundArguments(int bound_argc, |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7350 Vector< Handle<Object> > arguments = HandleVector(&constructor, 1); | 7676 Vector< Handle<Object> > arguments = HandleVector(&constructor, 1); |
| 7351 Handle<Object> type_error = | 7677 Handle<Object> type_error = |
| 7352 isolate->factory()->NewTypeError("not_constructor", arguments); | 7678 isolate->factory()->NewTypeError("not_constructor", arguments); |
| 7353 return isolate->Throw(*type_error); | 7679 return isolate->Throw(*type_error); |
| 7354 } | 7680 } |
| 7355 | 7681 |
| 7356 Handle<JSFunction> function = Handle<JSFunction>::cast(constructor); | 7682 Handle<JSFunction> function = Handle<JSFunction>::cast(constructor); |
| 7357 | 7683 |
| 7358 // If function should not have prototype, construction is not allowed. In this | 7684 // If function should not have prototype, construction is not allowed. In this |
| 7359 // case generated code bailouts here, since function has no initial_map. | 7685 // case generated code bailouts here, since function has no initial_map. |
| 7360 if (!function->should_have_prototype()) { | 7686 if (!function->should_have_prototype() && !function->shared()->bound()) { |
| 7361 Vector< Handle<Object> > arguments = HandleVector(&constructor, 1); | 7687 Vector< Handle<Object> > arguments = HandleVector(&constructor, 1); |
| 7362 Handle<Object> type_error = | 7688 Handle<Object> type_error = |
| 7363 isolate->factory()->NewTypeError("not_constructor", arguments); | 7689 isolate->factory()->NewTypeError("not_constructor", arguments); |
| 7364 return isolate->Throw(*type_error); | 7690 return isolate->Throw(*type_error); |
| 7365 } | 7691 } |
| 7366 | 7692 |
| 7367 #ifdef ENABLE_DEBUGGER_SUPPORT | 7693 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 7368 Debug* debug = isolate->debug(); | 7694 Debug* debug = isolate->debug(); |
| 7369 // Handle stepping into constructors if step into is active. | 7695 // Handle stepping into constructors if step into is active. |
| 7370 if (debug->StepInActive()) { | 7696 if (debug->StepInActive()) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7491 function->ReplaceCode(function->shared()->code()); | 7817 function->ReplaceCode(function->shared()->code()); |
| 7492 return function->code(); | 7818 return function->code(); |
| 7493 } | 7819 } |
| 7494 | 7820 |
| 7495 | 7821 |
| 7496 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) { | 7822 RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) { |
| 7497 HandleScope scope(isolate); | 7823 HandleScope scope(isolate); |
| 7498 ASSERT(args.length() == 1); | 7824 ASSERT(args.length() == 1); |
| 7499 RUNTIME_ASSERT(args[0]->IsSmi()); | 7825 RUNTIME_ASSERT(args[0]->IsSmi()); |
| 7500 Deoptimizer::BailoutType type = | 7826 Deoptimizer::BailoutType type = |
| 7501 static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value()); | 7827 static_cast<Deoptimizer::BailoutType>(args.smi_at(0)); |
| 7502 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); | 7828 Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); |
| 7503 ASSERT(isolate->heap()->IsAllocationAllowed()); | 7829 ASSERT(isolate->heap()->IsAllocationAllowed()); |
| 7504 int frames = deoptimizer->output_count(); | 7830 int frames = deoptimizer->output_count(); |
| 7505 | 7831 |
| 7506 deoptimizer->MaterializeHeapNumbers(); | 7832 deoptimizer->MaterializeHeapNumbers(); |
| 7507 delete deoptimizer; | 7833 delete deoptimizer; |
| 7508 | 7834 |
| 7509 JavaScriptFrameIterator it(isolate); | 7835 JavaScriptFrameIterator it(isolate); |
| 7510 JavaScriptFrame* frame = NULL; | 7836 JavaScriptFrame* frame = NULL; |
| 7511 for (int i = 0; i < frames - 1; i++) it.Advance(); | 7837 for (int i = 0; i < frames - 1; i++) it.Advance(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 7522 arguments = Handle<Object>( | 7848 arguments = Handle<Object>( |
| 7523 Accessors::FunctionGetArguments(*function, | 7849 Accessors::FunctionGetArguments(*function, |
| 7524 NULL)->ToObjectUnchecked()); | 7850 NULL)->ToObjectUnchecked()); |
| 7525 ASSERT(*arguments != isolate->heap()->null_value()); | 7851 ASSERT(*arguments != isolate->heap()->null_value()); |
| 7526 ASSERT(*arguments != isolate->heap()->undefined_value()); | 7852 ASSERT(*arguments != isolate->heap()->undefined_value()); |
| 7527 } | 7853 } |
| 7528 frame->SetExpression(i, *arguments); | 7854 frame->SetExpression(i, *arguments); |
| 7529 } | 7855 } |
| 7530 } | 7856 } |
| 7531 | 7857 |
| 7532 isolate->compilation_cache()->MarkForLazyOptimizing(function); | |
| 7533 if (type == Deoptimizer::EAGER) { | 7858 if (type == Deoptimizer::EAGER) { |
| 7534 RUNTIME_ASSERT(function->IsOptimized()); | 7859 RUNTIME_ASSERT(function->IsOptimized()); |
| 7535 } else { | 7860 } else { |
| 7536 RUNTIME_ASSERT(!function->IsOptimized()); | 7861 RUNTIME_ASSERT(!function->IsOptimized()); |
| 7537 } | 7862 } |
| 7538 | 7863 |
| 7539 // Avoid doing too much work when running with --always-opt and keep | 7864 // Avoid doing too much work when running with --always-opt and keep |
| 7540 // the optimized code around. | 7865 // the optimized code around. |
| 7541 if (FLAG_always_opt || type == Deoptimizer::LAZY) { | 7866 if (FLAG_always_opt || type == Deoptimizer::LAZY) { |
| 7542 return isolate->heap()->undefined_value(); | 7867 return isolate->heap()->undefined_value(); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7578 ASSERT(args.length() == 1); | 7903 ASSERT(args.length() == 1); |
| 7579 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 7904 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 7580 if (!function->IsOptimized()) return isolate->heap()->undefined_value(); | 7905 if (!function->IsOptimized()) return isolate->heap()->undefined_value(); |
| 7581 | 7906 |
| 7582 Deoptimizer::DeoptimizeFunction(*function); | 7907 Deoptimizer::DeoptimizeFunction(*function); |
| 7583 | 7908 |
| 7584 return isolate->heap()->undefined_value(); | 7909 return isolate->heap()->undefined_value(); |
| 7585 } | 7910 } |
| 7586 | 7911 |
| 7587 | 7912 |
| 7913 RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) { |
| 7914 #if defined(USE_SIMULATOR) |
| 7915 return isolate->heap()->true_value(); |
| 7916 #else |
| 7917 return isolate->heap()->false_value(); |
| 7918 #endif |
| 7919 } |
| 7920 |
| 7921 |
| 7588 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) { | 7922 RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) { |
| 7589 HandleScope scope(isolate); | 7923 HandleScope scope(isolate); |
| 7590 ASSERT(args.length() == 1); | 7924 ASSERT(args.length() == 1); |
| 7591 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 7925 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 7592 if (!function->IsOptimizable()) return isolate->heap()->undefined_value(); | 7926 if (!function->IsOptimizable()) return isolate->heap()->undefined_value(); |
| 7593 function->MarkForLazyRecompilation(); | 7927 function->MarkForLazyRecompilation(); |
| 7594 return isolate->heap()->undefined_value(); | 7928 return isolate->heap()->undefined_value(); |
| 7595 } | 7929 } |
| 7596 | 7930 |
| 7597 | 7931 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 7617 return Smi::FromInt(function->shared()->opt_count()); | 7951 return Smi::FromInt(function->shared()->opt_count()); |
| 7618 } | 7952 } |
| 7619 | 7953 |
| 7620 | 7954 |
| 7621 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { | 7955 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { |
| 7622 HandleScope scope(isolate); | 7956 HandleScope scope(isolate); |
| 7623 ASSERT(args.length() == 1); | 7957 ASSERT(args.length() == 1); |
| 7624 CONVERT_ARG_CHECKED(JSFunction, function, 0); | 7958 CONVERT_ARG_CHECKED(JSFunction, function, 0); |
| 7625 | 7959 |
| 7626 // We're not prepared to handle a function with arguments object. | 7960 // We're not prepared to handle a function with arguments object. |
| 7627 ASSERT(!function->shared()->scope_info()->HasArgumentsShadow()); | 7961 ASSERT(!function->shared()->uses_arguments()); |
| 7628 | 7962 |
| 7629 // We have hit a back edge in an unoptimized frame for a function that was | 7963 // We have hit a back edge in an unoptimized frame for a function that was |
| 7630 // selected for on-stack replacement. Find the unoptimized code object. | 7964 // selected for on-stack replacement. Find the unoptimized code object. |
| 7631 Handle<Code> unoptimized(function->shared()->code(), isolate); | 7965 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 7632 // Keep track of whether we've succeeded in optimizing. | 7966 // Keep track of whether we've succeeded in optimizing. |
| 7633 bool succeeded = unoptimized->optimizable(); | 7967 bool succeeded = unoptimized->optimizable(); |
| 7634 if (succeeded) { | 7968 if (succeeded) { |
| 7635 // If we are trying to do OSR when there are already optimized | 7969 // If we are trying to do OSR when there are already optimized |
| 7636 // activations of the function, it means (a) the function is directly or | 7970 // activations of the function, it means (a) the function is directly or |
| 7637 // indirectly recursive and (b) an optimized invocation has been | 7971 // indirectly recursive and (b) an optimized invocation has been |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7741 | 8075 |
| 7742 | 8076 |
| 7743 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) { | 8077 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) { |
| 7744 HandleScope scope(isolate); | 8078 HandleScope scope(isolate); |
| 7745 ASSERT(args.length() == 1); | 8079 ASSERT(args.length() == 1); |
| 7746 RUNTIME_ASSERT(!args[0]->IsJSFunction()); | 8080 RUNTIME_ASSERT(!args[0]->IsJSFunction()); |
| 7747 return *Execution::GetConstructorDelegate(args.at<Object>(0)); | 8081 return *Execution::GetConstructorDelegate(args.at<Object>(0)); |
| 7748 } | 8082 } |
| 7749 | 8083 |
| 7750 | 8084 |
| 7751 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewContext) { | 8085 RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) { |
| 7752 NoHandleAllocation ha; | 8086 NoHandleAllocation ha; |
| 7753 ASSERT(args.length() == 1); | 8087 ASSERT(args.length() == 1); |
| 7754 | 8088 |
| 7755 CONVERT_CHECKED(JSFunction, function, args[0]); | 8089 CONVERT_CHECKED(JSFunction, function, args[0]); |
| 7756 int length = function->shared()->scope_info()->NumberOfContextSlots(); | 8090 int length = function->shared()->scope_info()->NumberOfContextSlots(); |
| 7757 Object* result; | 8091 Object* result; |
| 7758 { MaybeObject* maybe_result = | 8092 { MaybeObject* maybe_result = |
| 7759 isolate->heap()->AllocateFunctionContext(length, function); | 8093 isolate->heap()->AllocateFunctionContext(length, function); |
| 7760 if (!maybe_result->ToObject(&result)) return maybe_result; | 8094 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 7761 } | 8095 } |
| 7762 | 8096 |
| 7763 isolate->set_context(Context::cast(result)); | 8097 isolate->set_context(Context::cast(result)); |
| 7764 | 8098 |
| 7765 return result; // non-failure | 8099 return result; // non-failure |
| 7766 } | 8100 } |
| 7767 | 8101 |
| 7768 | 8102 |
| 7769 MUST_USE_RESULT static MaybeObject* PushContextHelper(Isolate* isolate, | 8103 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) { |
| 7770 Object* object, | 8104 NoHandleAllocation ha; |
| 7771 bool is_catch_context) { | 8105 ASSERT(args.length() == 2); |
| 7772 // Convert the object to a proper JavaScript object. | 8106 JSObject* extension_object; |
| 7773 Object* js_object = object; | 8107 if (args[0]->IsJSObject()) { |
| 7774 if (!js_object->IsJSObject()) { | 8108 extension_object = JSObject::cast(args[0]); |
| 7775 MaybeObject* maybe_js_object = js_object->ToObject(); | 8109 } else { |
| 7776 if (!maybe_js_object->ToObject(&js_object)) { | 8110 // Convert the object to a proper JavaScript object. |
| 7777 if (!Failure::cast(maybe_js_object)->IsInternalError()) { | 8111 MaybeObject* maybe_js_object = args[0]->ToObject(); |
| 8112 if (!maybe_js_object->To(&extension_object)) { |
| 8113 if (Failure::cast(maybe_js_object)->IsInternalError()) { |
| 8114 HandleScope scope(isolate); |
| 8115 Handle<Object> handle = args.at<Object>(0); |
| 8116 Handle<Object> result = |
| 8117 isolate->factory()->NewTypeError("with_expression", |
| 8118 HandleVector(&handle, 1)); |
| 8119 return isolate->Throw(*result); |
| 8120 } else { |
| 7778 return maybe_js_object; | 8121 return maybe_js_object; |
| 7779 } | 8122 } |
| 7780 HandleScope scope(isolate); | |
| 7781 Handle<Object> handle(object, isolate); | |
| 7782 Handle<Object> result = | |
| 7783 isolate->factory()->NewTypeError("with_expression", | |
| 7784 HandleVector(&handle, 1)); | |
| 7785 return isolate->Throw(*result); | |
| 7786 } | 8123 } |
| 7787 } | 8124 } |
| 7788 | 8125 |
| 7789 Object* result; | 8126 JSFunction* function; |
| 7790 { MaybeObject* maybe_result = isolate->heap()->AllocateWithContext( | 8127 if (args[1]->IsSmi()) { |
| 7791 isolate->context(), JSObject::cast(js_object), is_catch_context); | 8128 // A smi sentinel indicates a context nested inside global code rather |
| 7792 if (!maybe_result->ToObject(&result)) return maybe_result; | 8129 // than some function. There is a canonical empty function that can be |
| 8130 // gotten from the global context. |
| 8131 function = isolate->context()->global_context()->closure(); |
| 8132 } else { |
| 8133 function = JSFunction::cast(args[1]); |
| 7793 } | 8134 } |
| 7794 | 8135 |
| 7795 Context* context = Context::cast(result); | 8136 Context* context; |
| 8137 MaybeObject* maybe_context = |
| 8138 isolate->heap()->AllocateWithContext(function, |
| 8139 isolate->context(), |
| 8140 extension_object); |
| 8141 if (!maybe_context->To(&context)) return maybe_context; |
| 7796 isolate->set_context(context); | 8142 isolate->set_context(context); |
| 7797 | 8143 return context; |
| 7798 return result; | |
| 7799 } | |
| 7800 | |
| 7801 | |
| 7802 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushContext) { | |
| 7803 NoHandleAllocation ha; | |
| 7804 ASSERT(args.length() == 1); | |
| 7805 return PushContextHelper(isolate, args[0], false); | |
| 7806 } | 8144 } |
| 7807 | 8145 |
| 7808 | 8146 |
| 7809 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) { | 8147 RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) { |
| 7810 NoHandleAllocation ha; | 8148 NoHandleAllocation ha; |
| 7811 ASSERT(args.length() == 1); | 8149 ASSERT(args.length() == 3); |
| 7812 return PushContextHelper(isolate, args[0], true); | 8150 String* name = String::cast(args[0]); |
| 8151 Object* thrown_object = args[1]; |
| 8152 JSFunction* function; |
| 8153 if (args[2]->IsSmi()) { |
| 8154 // A smi sentinel indicates a context nested inside global code rather |
| 8155 // than some function. There is a canonical empty function that can be |
| 8156 // gotten from the global context. |
| 8157 function = isolate->context()->global_context()->closure(); |
| 8158 } else { |
| 8159 function = JSFunction::cast(args[2]); |
| 8160 } |
| 8161 Context* context; |
| 8162 MaybeObject* maybe_context = |
| 8163 isolate->heap()->AllocateCatchContext(function, |
| 8164 isolate->context(), |
| 8165 name, |
| 8166 thrown_object); |
| 8167 if (!maybe_context->To(&context)) return maybe_context; |
| 8168 isolate->set_context(context); |
| 8169 return context; |
| 7813 } | 8170 } |
| 7814 | 8171 |
| 7815 | 8172 |
| 7816 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) { | 8173 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) { |
| 7817 HandleScope scope(isolate); | 8174 HandleScope scope(isolate); |
| 7818 ASSERT(args.length() == 2); | 8175 ASSERT(args.length() == 2); |
| 7819 | 8176 |
| 7820 CONVERT_ARG_CHECKED(Context, context, 0); | 8177 CONVERT_ARG_CHECKED(Context, context, 0); |
| 7821 CONVERT_ARG_CHECKED(String, name, 1); | 8178 CONVERT_ARG_CHECKED(String, name, 1); |
| 7822 | 8179 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7992 } | 8349 } |
| 7993 | 8350 |
| 7994 | 8351 |
| 7995 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) { | 8352 RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) { |
| 7996 HandleScope scope(isolate); | 8353 HandleScope scope(isolate); |
| 7997 ASSERT(args.length() == 4); | 8354 ASSERT(args.length() == 4); |
| 7998 | 8355 |
| 7999 Handle<Object> value(args[0], isolate); | 8356 Handle<Object> value(args[0], isolate); |
| 8000 CONVERT_ARG_CHECKED(Context, context, 1); | 8357 CONVERT_ARG_CHECKED(Context, context, 1); |
| 8001 CONVERT_ARG_CHECKED(String, name, 2); | 8358 CONVERT_ARG_CHECKED(String, name, 2); |
| 8002 CONVERT_SMI_CHECKED(strict_unchecked, args[3]); | 8359 CONVERT_SMI_ARG_CHECKED(strict_unchecked, 3); |
| 8003 RUNTIME_ASSERT(strict_unchecked == kStrictMode || | 8360 RUNTIME_ASSERT(strict_unchecked == kStrictMode || |
| 8004 strict_unchecked == kNonStrictMode); | 8361 strict_unchecked == kNonStrictMode); |
| 8005 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked); | 8362 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked); |
| 8006 | 8363 |
| 8007 int index; | 8364 int index; |
| 8008 PropertyAttributes attributes; | 8365 PropertyAttributes attributes; |
| 8009 ContextLookupFlags flags = FOLLOW_CHAINS; | 8366 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 8010 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); | 8367 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 8011 | 8368 |
| 8012 if (index >= 0) { | 8369 if (index >= 0) { |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8306 } else { | 8663 } else { |
| 8307 return isolate->heap()->null_value(); | 8664 return isolate->heap()->null_value(); |
| 8308 } | 8665 } |
| 8309 } | 8666 } |
| 8310 | 8667 |
| 8311 | 8668 |
| 8312 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) { | 8669 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) { |
| 8313 NoHandleAllocation ha; | 8670 NoHandleAllocation ha; |
| 8314 ASSERT(args.length() == 1); | 8671 ASSERT(args.length() == 1); |
| 8315 | 8672 |
| 8316 CONVERT_DOUBLE_CHECKED(x, args[0]); | 8673 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 8317 const char* zone = OS::LocalTimezone(x); | 8674 const char* zone = OS::LocalTimezone(x); |
| 8318 return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone)); | 8675 return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone)); |
| 8319 } | 8676 } |
| 8320 | 8677 |
| 8321 | 8678 |
| 8322 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimeOffset) { | 8679 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimeOffset) { |
| 8323 NoHandleAllocation ha; | 8680 NoHandleAllocation ha; |
| 8324 ASSERT(args.length() == 0); | 8681 ASSERT(args.length() == 0); |
| 8325 | 8682 |
| 8326 return isolate->heap()->NumberFromDouble(OS::LocalTimeOffset()); | 8683 return isolate->heap()->NumberFromDouble(OS::LocalTimeOffset()); |
| 8327 } | 8684 } |
| 8328 | 8685 |
| 8329 | 8686 |
| 8330 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateDaylightSavingsOffset) { | 8687 RUNTIME_FUNCTION(MaybeObject*, Runtime_DateDaylightSavingsOffset) { |
| 8331 NoHandleAllocation ha; | 8688 NoHandleAllocation ha; |
| 8332 ASSERT(args.length() == 1); | 8689 ASSERT(args.length() == 1); |
| 8333 | 8690 |
| 8334 CONVERT_DOUBLE_CHECKED(x, args[0]); | 8691 CONVERT_DOUBLE_ARG_CHECKED(x, 0); |
| 8335 return isolate->heap()->NumberFromDouble(OS::DaylightSavingsOffset(x)); | 8692 return isolate->heap()->NumberFromDouble(OS::DaylightSavingsOffset(x)); |
| 8336 } | 8693 } |
| 8337 | 8694 |
| 8338 | 8695 |
| 8339 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) { | 8696 RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) { |
| 8340 ASSERT(args.length() == 1); | 8697 ASSERT(args.length() == 1); |
| 8341 Object* global = args[0]; | 8698 Object* global = args[0]; |
| 8342 if (!global->IsJSGlobalObject()) return isolate->heap()->null_value(); | 8699 if (!global->IsJSGlobalObject()) return isolate->heap()->null_value(); |
| 8343 return JSGlobalObject::cast(global)->global_receiver(); | 8700 return JSGlobalObject::cast(global)->global_receiver(); |
| 8344 } | 8701 } |
| 8345 | 8702 |
| 8346 | 8703 |
| 8347 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) { | 8704 RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) { |
| 8348 HandleScope scope(isolate); | 8705 HandleScope scope(isolate); |
| 8349 ASSERT_EQ(1, args.length()); | 8706 ASSERT_EQ(1, args.length()); |
| 8350 CONVERT_ARG_CHECKED(String, source, 0); | 8707 CONVERT_ARG_CHECKED(String, source, 0); |
| 8351 | 8708 |
| 8352 Handle<Object> result = JsonParser::Parse(source); | 8709 source = Handle<String>(source->TryFlattenGetString()); |
| 8710 // Optimized fast case where we only have ascii characters. |
| 8711 Handle<Object> result; |
| 8712 if (source->IsSeqAsciiString()) { |
| 8713 result = JsonParser<true>::Parse(source); |
| 8714 } else { |
| 8715 result = JsonParser<false>::Parse(source); |
| 8716 } |
| 8353 if (result.is_null()) { | 8717 if (result.is_null()) { |
| 8354 // Syntax error or stack overflow in scanner. | 8718 // Syntax error or stack overflow in scanner. |
| 8355 ASSERT(isolate->has_pending_exception()); | 8719 ASSERT(isolate->has_pending_exception()); |
| 8356 return Failure::Exception(); | 8720 return Failure::Exception(); |
| 8357 } | 8721 } |
| 8358 return *result; | 8722 return *result; |
| 8359 } | 8723 } |
| 8360 | 8724 |
| 8361 | 8725 |
| 8362 bool CodeGenerationFromStringsAllowed(Isolate* isolate, | 8726 bool CodeGenerationFromStringsAllowed(Isolate* isolate, |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8458 // it is bound in the global context. | 8822 // it is bound in the global context. |
| 8459 int index = -1; | 8823 int index = -1; |
| 8460 PropertyAttributes attributes = ABSENT; | 8824 PropertyAttributes attributes = ABSENT; |
| 8461 while (true) { | 8825 while (true) { |
| 8462 receiver = context->Lookup(isolate->factory()->eval_symbol(), | 8826 receiver = context->Lookup(isolate->factory()->eval_symbol(), |
| 8463 FOLLOW_PROTOTYPE_CHAIN, | 8827 FOLLOW_PROTOTYPE_CHAIN, |
| 8464 &index, &attributes); | 8828 &index, &attributes); |
| 8465 // Stop search when eval is found or when the global context is | 8829 // Stop search when eval is found or when the global context is |
| 8466 // reached. | 8830 // reached. |
| 8467 if (attributes != ABSENT || context->IsGlobalContext()) break; | 8831 if (attributes != ABSENT || context->IsGlobalContext()) break; |
| 8468 if (context->is_function_context()) { | 8832 context = Handle<Context>(context->previous(), isolate); |
| 8469 context = Handle<Context>(Context::cast(context->closure()->context()), | |
| 8470 isolate); | |
| 8471 } else { | |
| 8472 context = Handle<Context>(context->previous(), isolate); | |
| 8473 } | |
| 8474 } | 8833 } |
| 8475 | 8834 |
| 8476 // If eval could not be resolved, it has been deleted and we need to | 8835 // If eval could not be resolved, it has been deleted and we need to |
| 8477 // throw a reference error. | 8836 // throw a reference error. |
| 8478 if (attributes == ABSENT) { | 8837 if (attributes == ABSENT) { |
| 8479 Handle<Object> name = isolate->factory()->eval_symbol(); | 8838 Handle<Object> name = isolate->factory()->eval_symbol(); |
| 8480 Handle<Object> reference_error = | 8839 Handle<Object> reference_error = |
| 8481 isolate->factory()->NewReferenceError("not_defined", | 8840 isolate->factory()->NewReferenceError("not_defined", |
| 8482 HandleVector(&name, 1)); | 8841 HandleVector(&name, 1)); |
| 8483 return MakePair(isolate->Throw(*reference_error), NULL); | 8842 return MakePair(isolate->Throw(*reference_error), NULL); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 8496 // Compare it to the builtin 'GlobalEval' function to make sure. | 8855 // Compare it to the builtin 'GlobalEval' function to make sure. |
| 8497 if (*callee != isolate->global_context()->global_eval_fun() || | 8856 if (*callee != isolate->global_context()->global_eval_fun() || |
| 8498 !args[1]->IsString()) { | 8857 !args[1]->IsString()) { |
| 8499 return MakePair(*callee, isolate->heap()->the_hole_value()); | 8858 return MakePair(*callee, isolate->heap()->the_hole_value()); |
| 8500 } | 8859 } |
| 8501 | 8860 |
| 8502 ASSERT(args[3]->IsSmi()); | 8861 ASSERT(args[3]->IsSmi()); |
| 8503 return CompileGlobalEval(isolate, | 8862 return CompileGlobalEval(isolate, |
| 8504 args.at<String>(1), | 8863 args.at<String>(1), |
| 8505 args.at<Object>(2), | 8864 args.at<Object>(2), |
| 8506 static_cast<StrictModeFlag>( | 8865 static_cast<StrictModeFlag>(args.smi_at(3))); |
| 8507 Smi::cast(args[3])->value())); | |
| 8508 } | 8866 } |
| 8509 | 8867 |
| 8510 | 8868 |
| 8511 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { | 8869 RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { |
| 8512 ASSERT(args.length() == 4); | 8870 ASSERT(args.length() == 4); |
| 8513 | 8871 |
| 8514 HandleScope scope(isolate); | 8872 HandleScope scope(isolate); |
| 8515 Handle<Object> callee = args.at<Object>(0); | 8873 Handle<Object> callee = args.at<Object>(0); |
| 8516 | 8874 |
| 8517 // 'eval' is bound in the global context, but it may have been overwritten. | 8875 // 'eval' is bound in the global context, but it may have been overwritten. |
| 8518 // Compare it to the builtin 'GlobalEval' function to make sure. | 8876 // Compare it to the builtin 'GlobalEval' function to make sure. |
| 8519 if (*callee != isolate->global_context()->global_eval_fun() || | 8877 if (*callee != isolate->global_context()->global_eval_fun() || |
| 8520 !args[1]->IsString()) { | 8878 !args[1]->IsString()) { |
| 8521 return MakePair(*callee, isolate->heap()->the_hole_value()); | 8879 return MakePair(*callee, isolate->heap()->the_hole_value()); |
| 8522 } | 8880 } |
| 8523 | 8881 |
| 8524 ASSERT(args[3]->IsSmi()); | 8882 ASSERT(args[3]->IsSmi()); |
| 8525 return CompileGlobalEval(isolate, | 8883 return CompileGlobalEval(isolate, |
| 8526 args.at<String>(1), | 8884 args.at<String>(1), |
| 8527 args.at<Object>(2), | 8885 args.at<Object>(2), |
| 8528 static_cast<StrictModeFlag>( | 8886 static_cast<StrictModeFlag>(args.smi_at(3))); |
| 8529 Smi::cast(args[3])->value())); | |
| 8530 } | 8887 } |
| 8531 | 8888 |
| 8532 | 8889 |
| 8533 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) { | 8890 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNewFunctionAttributes) { |
| 8534 // This utility adjusts the property attributes for newly created Function | 8891 // This utility adjusts the property attributes for newly created Function |
| 8535 // object ("new Function(...)") by changing the map. | 8892 // object ("new Function(...)") by changing the map. |
| 8536 // All it does is changing the prototype property to enumerable | 8893 // All it does is changing the prototype property to enumerable |
| 8537 // as specified in ECMA262, 15.3.5.2. | 8894 // as specified in ECMA262, 15.3.5.2. |
| 8538 HandleScope scope(isolate); | 8895 HandleScope scope(isolate); |
| 8539 ASSERT(args.length() == 1); | 8896 ASSERT(args.length() == 1); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8580 CONVERT_CHECKED(JSArray, array, args[0]); | 8937 CONVERT_CHECKED(JSArray, array, args[0]); |
| 8581 CONVERT_CHECKED(JSObject, element, args[1]); | 8938 CONVERT_CHECKED(JSObject, element, args[1]); |
| 8582 RUNTIME_ASSERT(array->HasFastElements()); | 8939 RUNTIME_ASSERT(array->HasFastElements()); |
| 8583 int length = Smi::cast(array->length())->value(); | 8940 int length = Smi::cast(array->length())->value(); |
| 8584 FixedArray* elements = FixedArray::cast(array->elements()); | 8941 FixedArray* elements = FixedArray::cast(array->elements()); |
| 8585 for (int i = 0; i < length; i++) { | 8942 for (int i = 0; i < length; i++) { |
| 8586 if (elements->get(i) == element) return isolate->heap()->false_value(); | 8943 if (elements->get(i) == element) return isolate->heap()->false_value(); |
| 8587 } | 8944 } |
| 8588 Object* obj; | 8945 Object* obj; |
| 8589 // Strict not needed. Used for cycle detection in Array join implementation. | 8946 // Strict not needed. Used for cycle detection in Array join implementation. |
| 8590 { MaybeObject* maybe_obj = array->SetFastElement(length, element, | 8947 { MaybeObject* maybe_obj = |
| 8591 kNonStrictMode); | 8948 array->SetFastElement(length, element, kNonStrictMode, true); |
| 8592 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8949 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8593 } | 8950 } |
| 8594 return isolate->heap()->true_value(); | 8951 return isolate->heap()->true_value(); |
| 8595 } | 8952 } |
| 8596 | 8953 |
| 8597 | 8954 |
| 8598 /** | 8955 /** |
| 8599 * A simple visitor visits every element of Array's. | 8956 * A simple visitor visits every element of Array's. |
| 8600 * The backend storage can be a fixed array for fast elements case, | 8957 * The backend storage can be a fixed array for fast elements case, |
| 8601 * or a dictionary for sparse array. Since Dictionary is a subtype | 8958 * or a dictionary for sparse array. Since Dictionary is a subtype |
| (...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9607 if (!maybe_result->ToObject(&result)) return maybe_result; | 9964 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 9608 } | 9965 } |
| 9609 | 9966 |
| 9610 // Count all frames which are relevant to debugging stack trace. | 9967 // Count all frames which are relevant to debugging stack trace. |
| 9611 int n = 0; | 9968 int n = 0; |
| 9612 StackFrame::Id id = isolate->debug()->break_frame_id(); | 9969 StackFrame::Id id = isolate->debug()->break_frame_id(); |
| 9613 if (id == StackFrame::NO_ID) { | 9970 if (id == StackFrame::NO_ID) { |
| 9614 // If there is no JavaScript stack frame count is 0. | 9971 // If there is no JavaScript stack frame count is 0. |
| 9615 return Smi::FromInt(0); | 9972 return Smi::FromInt(0); |
| 9616 } | 9973 } |
| 9617 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) n++; | 9974 |
| 9975 for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) { |
| 9976 n += it.frame()->GetInlineCount(); |
| 9977 } |
| 9618 return Smi::FromInt(n); | 9978 return Smi::FromInt(n); |
| 9619 } | 9979 } |
| 9620 | 9980 |
| 9621 | 9981 |
| 9622 static const int kFrameDetailsFrameIdIndex = 0; | 9982 static const int kFrameDetailsFrameIdIndex = 0; |
| 9623 static const int kFrameDetailsReceiverIndex = 1; | 9983 static const int kFrameDetailsReceiverIndex = 1; |
| 9624 static const int kFrameDetailsFunctionIndex = 2; | 9984 static const int kFrameDetailsFunctionIndex = 2; |
| 9625 static const int kFrameDetailsArgumentCountIndex = 3; | 9985 static const int kFrameDetailsArgumentCountIndex = 3; |
| 9626 static const int kFrameDetailsLocalCountIndex = 4; | 9986 static const int kFrameDetailsLocalCountIndex = 4; |
| 9627 static const int kFrameDetailsSourcePositionIndex = 5; | 9987 static const int kFrameDetailsSourcePositionIndex = 5; |
| 9628 static const int kFrameDetailsConstructCallIndex = 6; | 9988 static const int kFrameDetailsConstructCallIndex = 6; |
| 9629 static const int kFrameDetailsAtReturnIndex = 7; | 9989 static const int kFrameDetailsAtReturnIndex = 7; |
| 9630 static const int kFrameDetailsDebuggerFrameIndex = 8; | 9990 static const int kFrameDetailsFlagsIndex = 8; |
| 9631 static const int kFrameDetailsFirstDynamicIndex = 9; | 9991 static const int kFrameDetailsFirstDynamicIndex = 9; |
| 9632 | 9992 |
| 9633 // Return an array with frame details | 9993 // Return an array with frame details |
| 9634 // args[0]: number: break id | 9994 // args[0]: number: break id |
| 9635 // args[1]: number: frame index | 9995 // args[1]: number: frame index |
| 9636 // | 9996 // |
| 9637 // The array returned contains the following information: | 9997 // The array returned contains the following information: |
| 9638 // 0: Frame id | 9998 // 0: Frame id |
| 9639 // 1: Receiver | 9999 // 1: Receiver |
| 9640 // 2: Function | 10000 // 2: Function |
| 9641 // 3: Argument count | 10001 // 3: Argument count |
| 9642 // 4: Local count | 10002 // 4: Local count |
| 9643 // 5: Source position | 10003 // 5: Source position |
| 9644 // 6: Constructor call | 10004 // 6: Constructor call |
| 9645 // 7: Is at return | 10005 // 7: Is at return |
| 9646 // 8: Debugger frame | 10006 // 8: Flags |
| 9647 // Arguments name, value | 10007 // Arguments name, value |
| 9648 // Locals name, value | 10008 // Locals name, value |
| 9649 // Return value if any | 10009 // Return value if any |
| 9650 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { | 10010 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) { |
| 9651 HandleScope scope(isolate); | 10011 HandleScope scope(isolate); |
| 9652 ASSERT(args.length() == 2); | 10012 ASSERT(args.length() == 2); |
| 9653 | 10013 |
| 9654 // Check arguments. | 10014 // Check arguments. |
| 9655 Object* check; | 10015 Object* check; |
| 9656 { MaybeObject* maybe_check = Runtime_CheckExecutionState( | 10016 { MaybeObject* maybe_check = Runtime_CheckExecutionState( |
| 9657 RUNTIME_ARGUMENTS(isolate, args)); | 10017 RUNTIME_ARGUMENTS(isolate, args)); |
| 9658 if (!maybe_check->ToObject(&check)) return maybe_check; | 10018 if (!maybe_check->ToObject(&check)) return maybe_check; |
| 9659 } | 10019 } |
| 9660 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); | 10020 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); |
| 9661 Heap* heap = isolate->heap(); | 10021 Heap* heap = isolate->heap(); |
| 9662 | 10022 |
| 9663 // Find the relevant frame with the requested index. | 10023 // Find the relevant frame with the requested index. |
| 9664 StackFrame::Id id = isolate->debug()->break_frame_id(); | 10024 StackFrame::Id id = isolate->debug()->break_frame_id(); |
| 9665 if (id == StackFrame::NO_ID) { | 10025 if (id == StackFrame::NO_ID) { |
| 9666 // If there are no JavaScript stack frames return undefined. | 10026 // If there are no JavaScript stack frames return undefined. |
| 9667 return heap->undefined_value(); | 10027 return heap->undefined_value(); |
| 9668 } | 10028 } |
| 10029 |
| 10030 int deoptimized_frame_index = -1; // Frame index in optimized frame. |
| 10031 DeoptimizedFrameInfo* deoptimized_frame = NULL; |
| 10032 |
| 9669 int count = 0; | 10033 int count = 0; |
| 9670 JavaScriptFrameIterator it(isolate, id); | 10034 JavaScriptFrameIterator it(isolate, id); |
| 9671 for (; !it.done(); it.Advance()) { | 10035 for (; !it.done(); it.Advance()) { |
| 9672 if (count == index) break; | 10036 if (index < count + it.frame()->GetInlineCount()) break; |
| 9673 count++; | 10037 count += it.frame()->GetInlineCount(); |
| 9674 } | 10038 } |
| 9675 if (it.done()) return heap->undefined_value(); | 10039 if (it.done()) return heap->undefined_value(); |
| 9676 | 10040 |
| 9677 bool is_optimized_frame = | 10041 if (it.frame()->is_optimized()) { |
| 9678 it.frame()->LookupCode()->kind() == Code::OPTIMIZED_FUNCTION; | 10042 deoptimized_frame_index = |
| 10043 it.frame()->GetInlineCount() - (index - count) - 1; |
| 10044 deoptimized_frame = Deoptimizer::DebuggerInspectableFrame( |
| 10045 it.frame(), |
| 10046 deoptimized_frame_index, |
| 10047 isolate); |
| 10048 } |
| 9679 | 10049 |
| 9680 // Traverse the saved contexts chain to find the active context for the | 10050 // Traverse the saved contexts chain to find the active context for the |
| 9681 // selected frame. | 10051 // selected frame. |
| 9682 SaveContext* save = isolate->save_context(); | 10052 SaveContext* save = isolate->save_context(); |
| 9683 while (save != NULL && !save->below(it.frame())) { | 10053 while (save != NULL && !save->below(it.frame())) { |
| 9684 save = save->prev(); | 10054 save = save->prev(); |
| 9685 } | 10055 } |
| 9686 ASSERT(save != NULL); | 10056 ASSERT(save != NULL); |
| 9687 | 10057 |
| 9688 // Get the frame id. | 10058 // Get the frame id. |
| 9689 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); | 10059 Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate); |
| 9690 | 10060 |
| 9691 // Find source position. | 10061 // Find source position. |
| 9692 int position = | 10062 int position = |
| 9693 it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); | 10063 it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); |
| 9694 | 10064 |
| 9695 // Check for constructor frame. | 10065 // Check for constructor frame. Inlined frames cannot be construct calls. |
| 9696 bool constructor = it.frame()->IsConstructor(); | 10066 bool inlined_frame = |
| 10067 it.frame()->is_optimized() && deoptimized_frame_index != 0; |
| 10068 bool constructor = !inlined_frame && it.frame()->IsConstructor(); |
| 9697 | 10069 |
| 9698 // Get scope info and read from it for local variable information. | 10070 // Get scope info and read from it for local variable information. |
| 9699 Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); | 10071 Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); |
| 9700 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); | 10072 Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); |
| 10073 ASSERT(*scope_info != SerializedScopeInfo::Empty()); |
| 9701 ScopeInfo<> info(*scope_info); | 10074 ScopeInfo<> info(*scope_info); |
| 9702 | 10075 |
| 9703 // Get the context. | |
| 9704 Handle<Context> context(Context::cast(it.frame()->context())); | |
| 9705 | |
| 9706 // Get the locals names and values into a temporary array. | 10076 // Get the locals names and values into a temporary array. |
| 9707 // | 10077 // |
| 9708 // TODO(1240907): Hide compiler-introduced stack variables | 10078 // TODO(1240907): Hide compiler-introduced stack variables |
| 9709 // (e.g. .result)? For users of the debugger, they will probably be | 10079 // (e.g. .result)? For users of the debugger, they will probably be |
| 9710 // confusing. | 10080 // confusing. |
| 9711 Handle<FixedArray> locals = | 10081 Handle<FixedArray> locals = |
| 9712 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); | 10082 isolate->factory()->NewFixedArray(info.NumberOfLocals() * 2); |
| 9713 | 10083 |
| 9714 // Fill in the names of the locals. | 10084 // Fill in the values of the locals. |
| 9715 for (int i = 0; i < info.NumberOfLocals(); i++) { | 10085 int i = 0; |
| 10086 for (; i < info.number_of_stack_slots(); ++i) { |
| 10087 // Use the value from the stack. |
| 9716 locals->set(i * 2, *info.LocalName(i)); | 10088 locals->set(i * 2, *info.LocalName(i)); |
| 9717 } | 10089 if (it.frame()->is_optimized()) { |
| 9718 | 10090 // Get the value from the deoptimized frame. |
| 9719 // Fill in the values of the locals. | 10091 locals->set(i * 2 + 1, |
| 9720 for (int i = 0; i < info.NumberOfLocals(); i++) { | 10092 deoptimized_frame->GetExpression(i)); |
| 9721 if (is_optimized_frame) { | 10093 } else { |
| 9722 // If we are inspecting an optimized frame use undefined as the | |
| 9723 // value for all locals. | |
| 9724 // | |
| 9725 // TODO(1140): We should be able to get the correct values | |
| 9726 // for locals in optimized frames. | |
| 9727 locals->set(i * 2 + 1, isolate->heap()->undefined_value()); | |
| 9728 } else if (i < info.number_of_stack_slots()) { | |
| 9729 // Get the value from the stack. | 10094 // Get the value from the stack. |
| 9730 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); | 10095 locals->set(i * 2 + 1, it.frame()->GetExpression(i)); |
| 9731 } else { | 10096 } |
| 9732 // Traverse the context chain to the function context as all local | 10097 } |
| 9733 // variables stored in the context will be on the function context. | 10098 if (i < info.NumberOfLocals()) { |
| 10099 // Get the context containing declarations. |
| 10100 Handle<Context> context( |
| 10101 Context::cast(it.frame()->context())->declaration_context()); |
| 10102 for (; i < info.NumberOfLocals(); ++i) { |
| 9734 Handle<String> name = info.LocalName(i); | 10103 Handle<String> name = info.LocalName(i); |
| 9735 while (!context->is_function_context()) { | 10104 locals->set(i * 2, *name); |
| 9736 context = Handle<Context>(context->previous()); | |
| 9737 } | |
| 9738 ASSERT(context->is_function_context()); | |
| 9739 locals->set(i * 2 + 1, | 10105 locals->set(i * 2 + 1, |
| 9740 context->get(scope_info->ContextSlotIndex(*name, NULL))); | 10106 context->get(scope_info->ContextSlotIndex(*name, NULL))); |
| 9741 } | 10107 } |
| 9742 } | 10108 } |
| 9743 | 10109 |
| 9744 // Check whether this frame is positioned at return. If not top | 10110 // Check whether this frame is positioned at return. If not top |
| 9745 // frame or if the frame is optimized it cannot be at a return. | 10111 // frame or if the frame is optimized it cannot be at a return. |
| 9746 bool at_return = false; | 10112 bool at_return = false; |
| 9747 if (!is_optimized_frame && index == 0) { | 10113 if (!it.frame()->is_optimized() && index == 0) { |
| 9748 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); | 10114 at_return = isolate->debug()->IsBreakAtReturn(it.frame()); |
| 9749 } | 10115 } |
| 9750 | 10116 |
| 9751 // If positioned just before return find the value to be returned and add it | 10117 // If positioned just before return find the value to be returned and add it |
| 9752 // to the frame information. | 10118 // to the frame information. |
| 9753 Handle<Object> return_value = isolate->factory()->undefined_value(); | 10119 Handle<Object> return_value = isolate->factory()->undefined_value(); |
| 9754 if (at_return) { | 10120 if (at_return) { |
| 9755 StackFrameIterator it2(isolate); | 10121 StackFrameIterator it2(isolate); |
| 9756 Address internal_frame_sp = NULL; | 10122 Address internal_frame_sp = NULL; |
| 9757 while (!it2.done()) { | 10123 while (!it2.done()) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 9782 | 10148 |
| 9783 // Now advance to the arguments adapter frame (if any). It contains all | 10149 // Now advance to the arguments adapter frame (if any). It contains all |
| 9784 // the provided parameters whereas the function frame always have the number | 10150 // the provided parameters whereas the function frame always have the number |
| 9785 // of arguments matching the functions parameters. The rest of the | 10151 // of arguments matching the functions parameters. The rest of the |
| 9786 // information (except for what is collected above) is the same. | 10152 // information (except for what is collected above) is the same. |
| 9787 it.AdvanceToArgumentsFrame(); | 10153 it.AdvanceToArgumentsFrame(); |
| 9788 | 10154 |
| 9789 // Find the number of arguments to fill. At least fill the number of | 10155 // Find the number of arguments to fill. At least fill the number of |
| 9790 // parameters for the function and fill more if more parameters are provided. | 10156 // parameters for the function and fill more if more parameters are provided. |
| 9791 int argument_count = info.number_of_parameters(); | 10157 int argument_count = info.number_of_parameters(); |
| 9792 if (argument_count < it.frame()->ComputeParametersCount()) { | 10158 if (it.frame()->is_optimized()) { |
| 9793 argument_count = it.frame()->ComputeParametersCount(); | 10159 ASSERT_EQ(argument_count, deoptimized_frame->parameters_count()); |
| 10160 } else { |
| 10161 if (argument_count < it.frame()->ComputeParametersCount()) { |
| 10162 argument_count = it.frame()->ComputeParametersCount(); |
| 10163 } |
| 9794 } | 10164 } |
| 9795 | 10165 |
| 9796 // Calculate the size of the result. | 10166 // Calculate the size of the result. |
| 9797 int details_size = kFrameDetailsFirstDynamicIndex + | 10167 int details_size = kFrameDetailsFirstDynamicIndex + |
| 9798 2 * (argument_count + info.NumberOfLocals()) + | 10168 2 * (argument_count + info.NumberOfLocals()) + |
| 9799 (at_return ? 1 : 0); | 10169 (at_return ? 1 : 0); |
| 9800 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); | 10170 Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); |
| 9801 | 10171 |
| 9802 // Add the frame id. | 10172 // Add the frame id. |
| 9803 details->set(kFrameDetailsFrameIdIndex, *frame_id); | 10173 details->set(kFrameDetailsFrameIdIndex, *frame_id); |
| 9804 | 10174 |
| 9805 // Add the function (same as in function frame). | 10175 // Add the function (same as in function frame). |
| 9806 details->set(kFrameDetailsFunctionIndex, it.frame()->function()); | 10176 if (it.frame()->is_optimized()) { |
| 10177 // Get the function from the deoptimized frame. |
| 10178 details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction()); |
| 10179 } else { |
| 10180 // Get the function from the stack. |
| 10181 details->set(kFrameDetailsFunctionIndex, it.frame()->function()); |
| 10182 } |
| 9807 | 10183 |
| 9808 // Add the arguments count. | 10184 // Add the arguments count. |
| 9809 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count)); | 10185 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count)); |
| 9810 | 10186 |
| 9811 // Add the locals count | 10187 // Add the locals count |
| 9812 details->set(kFrameDetailsLocalCountIndex, | 10188 details->set(kFrameDetailsLocalCountIndex, |
| 9813 Smi::FromInt(info.NumberOfLocals())); | 10189 Smi::FromInt(info.NumberOfLocals())); |
| 9814 | 10190 |
| 9815 // Add the source position. | 10191 // Add the source position. |
| 9816 if (position != RelocInfo::kNoPosition) { | 10192 if (position != RelocInfo::kNoPosition) { |
| 9817 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position)); | 10193 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position)); |
| 9818 } else { | 10194 } else { |
| 9819 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); | 10195 details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value()); |
| 9820 } | 10196 } |
| 9821 | 10197 |
| 9822 // Add the constructor information. | 10198 // Add the constructor information. |
| 9823 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); | 10199 details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor)); |
| 9824 | 10200 |
| 9825 // Add the at return information. | 10201 // Add the at return information. |
| 9826 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); | 10202 details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return)); |
| 9827 | 10203 |
| 9828 // Add information on whether this frame is invoked in the debugger context. | 10204 // Add flags to indicate information on whether this frame is |
| 9829 details->set(kFrameDetailsDebuggerFrameIndex, | 10205 // bit 0: invoked in the debugger context. |
| 9830 heap->ToBoolean(*save->context() == | 10206 // bit 1: optimized frame. |
| 9831 *isolate->debug()->debug_context())); | 10207 // bit 2: inlined in optimized frame |
| 10208 int flags = 0; |
| 10209 if (*save->context() == *isolate->debug()->debug_context()) { |
| 10210 flags |= 1 << 0; |
| 10211 } |
| 10212 if (it.frame()->is_optimized()) { |
| 10213 flags |= 1 << 1; |
| 10214 if (deoptimized_frame_index > 0) { |
| 10215 flags |= 1 << 2; |
| 10216 } |
| 10217 } |
| 10218 details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); |
| 9832 | 10219 |
| 9833 // Fill the dynamic part. | 10220 // Fill the dynamic part. |
| 9834 int details_index = kFrameDetailsFirstDynamicIndex; | 10221 int details_index = kFrameDetailsFirstDynamicIndex; |
| 9835 | 10222 |
| 9836 // Add arguments name and value. | 10223 // Add arguments name and value. |
| 9837 for (int i = 0; i < argument_count; i++) { | 10224 for (int i = 0; i < argument_count; i++) { |
| 9838 // Name of the argument. | 10225 // Name of the argument. |
| 9839 if (i < info.number_of_parameters()) { | 10226 if (i < info.number_of_parameters()) { |
| 9840 details->set(details_index++, *info.parameter_name(i)); | 10227 details->set(details_index++, *info.parameter_name(i)); |
| 9841 } else { | 10228 } else { |
| 9842 details->set(details_index++, heap->undefined_value()); | 10229 details->set(details_index++, heap->undefined_value()); |
| 9843 } | 10230 } |
| 9844 | 10231 |
| 9845 // Parameter value. If we are inspecting an optimized frame, use | 10232 // Parameter value. |
| 9846 // undefined as the value. | 10233 if (it.frame()->is_optimized()) { |
| 9847 // | 10234 // Get the value from the deoptimized frame. |
| 9848 // TODO(3141533): We should be able to get the actual parameter | 10235 details->set(details_index++, deoptimized_frame->GetParameter(i)); |
| 9849 // value for optimized frames. | |
| 9850 if (!is_optimized_frame && | |
| 9851 (i < it.frame()->ComputeParametersCount())) { | |
| 9852 details->set(details_index++, it.frame()->GetParameter(i)); | |
| 9853 } else { | 10236 } else { |
| 9854 details->set(details_index++, heap->undefined_value()); | 10237 if (i < it.frame()->ComputeParametersCount()) { |
| 10238 // Get the value from the stack. |
| 10239 details->set(details_index++, it.frame()->GetParameter(i)); |
| 10240 } else { |
| 10241 details->set(details_index++, heap->undefined_value()); |
| 10242 } |
| 9855 } | 10243 } |
| 9856 } | 10244 } |
| 9857 | 10245 |
| 9858 // Add locals name and value from the temporary copy from the function frame. | 10246 // Add locals name and value from the temporary copy from the function frame. |
| 9859 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { | 10247 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { |
| 9860 details->set(details_index++, locals->get(i)); | 10248 details->set(details_index++, locals->get(i)); |
| 9861 } | 10249 } |
| 9862 | 10250 |
| 9863 // Add the value being returned. | 10251 // Add the value being returned. |
| 9864 if (at_return) { | 10252 if (at_return) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 9876 // by creating correct wrapper object based on the calling frame's | 10264 // by creating correct wrapper object based on the calling frame's |
| 9877 // global context. | 10265 // global context. |
| 9878 it.Advance(); | 10266 it.Advance(); |
| 9879 Handle<Context> calling_frames_global_context( | 10267 Handle<Context> calling_frames_global_context( |
| 9880 Context::cast(Context::cast(it.frame()->context())->global_context())); | 10268 Context::cast(Context::cast(it.frame()->context())->global_context())); |
| 9881 receiver = | 10269 receiver = |
| 9882 isolate->factory()->ToObject(receiver, calling_frames_global_context); | 10270 isolate->factory()->ToObject(receiver, calling_frames_global_context); |
| 9883 } | 10271 } |
| 9884 details->set(kFrameDetailsReceiverIndex, *receiver); | 10272 details->set(kFrameDetailsReceiverIndex, *receiver); |
| 9885 | 10273 |
| 10274 // Get rid of the calculated deoptimized frame if any. |
| 10275 if (deoptimized_frame != NULL) { |
| 10276 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame, |
| 10277 isolate); |
| 10278 } |
| 10279 |
| 9886 ASSERT_EQ(details_size, details_index); | 10280 ASSERT_EQ(details_size, details_index); |
| 9887 return *isolate->factory()->NewJSArrayWithElements(details); | 10281 return *isolate->factory()->NewJSArrayWithElements(details); |
| 9888 } | 10282 } |
| 9889 | 10283 |
| 9890 | 10284 |
| 9891 // Copy all the context locals into an object used to materialize a scope. | 10285 // Copy all the context locals into an object used to materialize a scope. |
| 9892 static bool CopyContextLocalsToScopeObject( | 10286 static bool CopyContextLocalsToScopeObject( |
| 9893 Isolate* isolate, | 10287 Isolate* isolate, |
| 9894 Handle<SerializedScopeInfo> serialized_scope_info, | 10288 Handle<SerializedScopeInfo> serialized_scope_info, |
| 9895 ScopeInfo<>& scope_info, | 10289 ScopeInfo<>& scope_info, |
| 9896 Handle<Context> context, | 10290 Handle<Context> context, |
| 9897 Handle<JSObject> scope_object) { | 10291 Handle<JSObject> scope_object) { |
| 9898 // Fill all context locals to the context extension. | 10292 // Fill all context locals to the context extension. |
| 9899 for (int i = Context::MIN_CONTEXT_SLOTS; | 10293 for (int i = Context::MIN_CONTEXT_SLOTS; |
| 9900 i < scope_info.number_of_context_slots(); | 10294 i < scope_info.number_of_context_slots(); |
| 9901 i++) { | 10295 i++) { |
| 9902 int context_index = serialized_scope_info->ContextSlotIndex( | 10296 int context_index = serialized_scope_info->ContextSlotIndex( |
| 9903 *scope_info.context_slot_name(i), NULL); | 10297 *scope_info.context_slot_name(i), NULL); |
| 9904 | 10298 |
| 9905 // Don't include the arguments shadow (.arguments) context variable. | 10299 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9906 if (*scope_info.context_slot_name(i) != | 10300 isolate, |
| 9907 isolate->heap()->arguments_shadow_symbol()) { | 10301 SetProperty(scope_object, |
| 9908 RETURN_IF_EMPTY_HANDLE_VALUE( | 10302 scope_info.context_slot_name(i), |
| 9909 isolate, | 10303 Handle<Object>(context->get(context_index), isolate), |
| 9910 SetProperty(scope_object, | 10304 NONE, |
| 9911 scope_info.context_slot_name(i), | 10305 kNonStrictMode), |
| 9912 Handle<Object>(context->get(context_index), isolate), | 10306 false); |
| 9913 NONE, | |
| 9914 kNonStrictMode), | |
| 9915 false); | |
| 9916 } | |
| 9917 } | 10307 } |
| 9918 | 10308 |
| 9919 return true; | 10309 return true; |
| 9920 } | 10310 } |
| 9921 | 10311 |
| 9922 | 10312 |
| 9923 // Create a plain JSObject which materializes the local scope for the specified | 10313 // Create a plain JSObject which materializes the local scope for the specified |
| 9924 // frame. | 10314 // frame. |
| 9925 static Handle<JSObject> MaterializeLocalScope(Isolate* isolate, | 10315 static Handle<JSObject> MaterializeLocalScope(Isolate* isolate, |
| 9926 JavaScriptFrame* frame) { | 10316 JavaScriptFrame* frame) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 9940 isolate, | 10330 isolate, |
| 9941 SetProperty(local_scope, | 10331 SetProperty(local_scope, |
| 9942 scope_info.parameter_name(i), | 10332 scope_info.parameter_name(i), |
| 9943 Handle<Object>(frame->GetParameter(i), isolate), | 10333 Handle<Object>(frame->GetParameter(i), isolate), |
| 9944 NONE, | 10334 NONE, |
| 9945 kNonStrictMode), | 10335 kNonStrictMode), |
| 9946 Handle<JSObject>()); | 10336 Handle<JSObject>()); |
| 9947 } | 10337 } |
| 9948 | 10338 |
| 9949 // Second fill all stack locals. | 10339 // Second fill all stack locals. |
| 9950 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) { | 10340 for (int i = 0; i < scope_info.number_of_stack_slots(); ++i) { |
| 9951 RETURN_IF_EMPTY_HANDLE_VALUE( | 10341 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9952 isolate, | 10342 isolate, |
| 9953 SetProperty(local_scope, | 10343 SetProperty(local_scope, |
| 9954 scope_info.stack_slot_name(i), | 10344 scope_info.stack_slot_name(i), |
| 9955 Handle<Object>(frame->GetExpression(i), isolate), | 10345 Handle<Object>(frame->GetExpression(i), isolate), |
| 9956 NONE, | 10346 NONE, |
| 9957 kNonStrictMode), | 10347 kNonStrictMode), |
| 9958 Handle<JSObject>()); | 10348 Handle<JSObject>()); |
| 9959 } | 10349 } |
| 9960 | 10350 |
| 9961 // Third fill all context locals. | 10351 if (scope_info.number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) { |
| 9962 Handle<Context> frame_context(Context::cast(frame->context())); | 10352 // Third fill all context locals. |
| 9963 Handle<Context> function_context(frame_context->fcontext()); | 10353 Handle<Context> frame_context(Context::cast(frame->context())); |
| 9964 if (!CopyContextLocalsToScopeObject(isolate, | 10354 Handle<Context> function_context(frame_context->declaration_context()); |
| 9965 serialized_scope_info, scope_info, | 10355 if (!CopyContextLocalsToScopeObject(isolate, |
| 9966 function_context, local_scope)) { | 10356 serialized_scope_info, scope_info, |
| 9967 return Handle<JSObject>(); | 10357 function_context, local_scope)) { |
| 9968 } | 10358 return Handle<JSObject>(); |
| 10359 } |
| 9969 | 10360 |
| 9970 // Finally copy any properties from the function context extension. This will | 10361 // Finally copy any properties from the function context extension. |
| 9971 // be variables introduced by eval. | 10362 // These will be variables introduced by eval. |
| 9972 if (function_context->closure() == *function) { | 10363 if (function_context->closure() == *function) { |
| 9973 if (function_context->has_extension() && | 10364 if (function_context->has_extension() && |
| 9974 !function_context->IsGlobalContext()) { | 10365 !function_context->IsGlobalContext()) { |
| 9975 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | 10366 Handle<JSObject> ext(JSObject::cast(function_context->extension())); |
| 9976 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); | 10367 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); |
| 9977 for (int i = 0; i < keys->length(); i++) { | 10368 for (int i = 0; i < keys->length(); i++) { |
| 9978 // Names of variables introduced by eval are strings. | 10369 // Names of variables introduced by eval are strings. |
| 9979 ASSERT(keys->get(i)->IsString()); | 10370 ASSERT(keys->get(i)->IsString()); |
| 9980 Handle<String> key(String::cast(keys->get(i))); | 10371 Handle<String> key(String::cast(keys->get(i))); |
| 9981 RETURN_IF_EMPTY_HANDLE_VALUE( | 10372 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9982 isolate, | 10373 isolate, |
| 9983 SetProperty(local_scope, | 10374 SetProperty(local_scope, |
| 9984 key, | 10375 key, |
| 9985 GetProperty(ext, key), | 10376 GetProperty(ext, key), |
| 9986 NONE, | 10377 NONE, |
| 9987 kNonStrictMode), | 10378 kNonStrictMode), |
| 9988 Handle<JSObject>()); | 10379 Handle<JSObject>()); |
| 10380 } |
| 9989 } | 10381 } |
| 9990 } | 10382 } |
| 9991 } | 10383 } |
| 10384 |
| 9992 return local_scope; | 10385 return local_scope; |
| 9993 } | 10386 } |
| 9994 | 10387 |
| 9995 | 10388 |
| 9996 // Create a plain JSObject which materializes the closure content for the | 10389 // Create a plain JSObject which materializes the closure content for the |
| 9997 // context. | 10390 // context. |
| 9998 static Handle<JSObject> MaterializeClosure(Isolate* isolate, | 10391 static Handle<JSObject> MaterializeClosure(Isolate* isolate, |
| 9999 Handle<Context> context) { | 10392 Handle<Context> context) { |
| 10000 ASSERT(context->is_function_context()); | 10393 ASSERT(context->IsFunctionContext()); |
| 10001 | 10394 |
| 10002 Handle<SharedFunctionInfo> shared(context->closure()->shared()); | 10395 Handle<SharedFunctionInfo> shared(context->closure()->shared()); |
| 10003 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); | 10396 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); |
| 10004 ScopeInfo<> scope_info(*serialized_scope_info); | 10397 ScopeInfo<> scope_info(*serialized_scope_info); |
| 10005 | 10398 |
| 10006 // Allocate and initialize a JSObject with all the content of theis function | 10399 // Allocate and initialize a JSObject with all the content of theis function |
| 10007 // closure. | 10400 // closure. |
| 10008 Handle<JSObject> closure_scope = | 10401 Handle<JSObject> closure_scope = |
| 10009 isolate->factory()->NewJSObject(isolate->object_function()); | 10402 isolate->factory()->NewJSObject(isolate->object_function()); |
| 10010 | 10403 |
| 10011 // Check whether the arguments shadow object exists. | |
| 10012 int arguments_shadow_index = | |
| 10013 shared->scope_info()->ContextSlotIndex( | |
| 10014 isolate->heap()->arguments_shadow_symbol(), NULL); | |
| 10015 if (arguments_shadow_index >= 0) { | |
| 10016 // In this case all the arguments are available in the arguments shadow | |
| 10017 // object. | |
| 10018 Handle<JSObject> arguments_shadow( | |
| 10019 JSObject::cast(context->get(arguments_shadow_index))); | |
| 10020 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { | |
| 10021 // We don't expect exception-throwing getters on the arguments shadow. | |
| 10022 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); | |
| 10023 RETURN_IF_EMPTY_HANDLE_VALUE( | |
| 10024 isolate, | |
| 10025 SetProperty(closure_scope, | |
| 10026 scope_info.parameter_name(i), | |
| 10027 Handle<Object>(element, isolate), | |
| 10028 NONE, | |
| 10029 kNonStrictMode), | |
| 10030 Handle<JSObject>()); | |
| 10031 } | |
| 10032 } | |
| 10033 | |
| 10034 // Fill all context locals to the context extension. | 10404 // Fill all context locals to the context extension. |
| 10035 if (!CopyContextLocalsToScopeObject(isolate, | 10405 if (!CopyContextLocalsToScopeObject(isolate, |
| 10036 serialized_scope_info, scope_info, | 10406 serialized_scope_info, scope_info, |
| 10037 context, closure_scope)) { | 10407 context, closure_scope)) { |
| 10038 return Handle<JSObject>(); | 10408 return Handle<JSObject>(); |
| 10039 } | 10409 } |
| 10040 | 10410 |
| 10041 // Finally copy any properties from the function context extension. This will | 10411 // Finally copy any properties from the function context extension. This will |
| 10042 // be variables introduced by eval. | 10412 // be variables introduced by eval. |
| 10043 if (context->has_extension()) { | 10413 if (context->has_extension()) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 10055 NONE, | 10425 NONE, |
| 10056 kNonStrictMode), | 10426 kNonStrictMode), |
| 10057 Handle<JSObject>()); | 10427 Handle<JSObject>()); |
| 10058 } | 10428 } |
| 10059 } | 10429 } |
| 10060 | 10430 |
| 10061 return closure_scope; | 10431 return closure_scope; |
| 10062 } | 10432 } |
| 10063 | 10433 |
| 10064 | 10434 |
| 10435 // Create a plain JSObject which materializes the scope for the specified |
| 10436 // catch context. |
| 10437 static Handle<JSObject> MaterializeCatchScope(Isolate* isolate, |
| 10438 Handle<Context> context) { |
| 10439 ASSERT(context->IsCatchContext()); |
| 10440 Handle<String> name(String::cast(context->extension())); |
| 10441 Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX)); |
| 10442 Handle<JSObject> catch_scope = |
| 10443 isolate->factory()->NewJSObject(isolate->object_function()); |
| 10444 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 10445 isolate, |
| 10446 SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode), |
| 10447 Handle<JSObject>()); |
| 10448 return catch_scope; |
| 10449 } |
| 10450 |
| 10451 |
| 10065 // Iterate over the actual scopes visible from a stack frame. All scopes are | 10452 // Iterate over the actual scopes visible from a stack frame. All scopes are |
| 10066 // backed by an actual context except the local scope, which is inserted | 10453 // backed by an actual context except the local scope, which is inserted |
| 10067 // "artifically" in the context chain. | 10454 // "artifically" in the context chain. |
| 10068 class ScopeIterator { | 10455 class ScopeIterator { |
| 10069 public: | 10456 public: |
| 10070 enum ScopeType { | 10457 enum ScopeType { |
| 10071 ScopeTypeGlobal = 0, | 10458 ScopeTypeGlobal = 0, |
| 10072 ScopeTypeLocal, | 10459 ScopeTypeLocal, |
| 10073 ScopeTypeWith, | 10460 ScopeTypeWith, |
| 10074 ScopeTypeClosure, | 10461 ScopeTypeClosure, |
| 10075 // Every catch block contains an implicit with block (its parameter is | |
| 10076 // a JSContextExtensionObject) that extends current scope with a variable | |
| 10077 // holding exception object. Such with blocks are treated as scopes of their | |
| 10078 // own type. | |
| 10079 ScopeTypeCatch | 10462 ScopeTypeCatch |
| 10080 }; | 10463 }; |
| 10081 | 10464 |
| 10082 ScopeIterator(Isolate* isolate, JavaScriptFrame* frame) | 10465 ScopeIterator(Isolate* isolate, JavaScriptFrame* frame) |
| 10083 : isolate_(isolate), | 10466 : isolate_(isolate), |
| 10084 frame_(frame), | 10467 frame_(frame), |
| 10085 function_(JSFunction::cast(frame->function())), | 10468 function_(JSFunction::cast(frame->function())), |
| 10086 context_(Context::cast(frame->context())), | 10469 context_(Context::cast(frame->context())), |
| 10087 local_done_(false), | 10470 local_done_(false), |
| 10088 at_local_(false) { | 10471 at_local_(false) { |
| 10089 | 10472 |
| 10090 // Check whether the first scope is actually a local scope. | 10473 // Check whether the first scope is actually a local scope. |
| 10091 if (context_->IsGlobalContext()) { | 10474 if (context_->IsGlobalContext()) { |
| 10092 // If there is a stack slot for .result then this local scope has been | 10475 // If there is a stack slot for .result then this local scope has been |
| 10093 // created for evaluating top level code and it is not a real local scope. | 10476 // created for evaluating top level code and it is not a real local scope. |
| 10094 // Checking for the existence of .result seems fragile, but the scope info | 10477 // Checking for the existence of .result seems fragile, but the scope info |
| 10095 // saved with the code object does not otherwise have that information. | 10478 // saved with the code object does not otherwise have that information. |
| 10096 int index = function_->shared()->scope_info()-> | 10479 int index = function_->shared()->scope_info()-> |
| 10097 StackSlotIndex(isolate_->heap()->result_symbol()); | 10480 StackSlotIndex(isolate_->heap()->result_symbol()); |
| 10098 at_local_ = index < 0; | 10481 at_local_ = index < 0; |
| 10099 } else if (context_->is_function_context()) { | 10482 } else if (context_->IsFunctionContext()) { |
| 10100 at_local_ = true; | 10483 at_local_ = true; |
| 10101 } else if (context_->closure() != *function_) { | 10484 } else if (context_->closure() != *function_) { |
| 10102 // The context_ is a with block from the outer function. | 10485 // The context_ is a with or catch block from the outer function. |
| 10103 ASSERT(context_->has_extension()); | 10486 ASSERT(context_->IsWithContext() || context_->IsCatchContext()); |
| 10104 at_local_ = true; | 10487 at_local_ = true; |
| 10105 } | 10488 } |
| 10106 } | 10489 } |
| 10107 | 10490 |
| 10108 // More scopes? | 10491 // More scopes? |
| 10109 bool Done() { return context_.is_null(); } | 10492 bool Done() { return context_.is_null(); } |
| 10110 | 10493 |
| 10111 // Move to the next scope. | 10494 // Move to the next scope. |
| 10112 void Next() { | 10495 void Next() { |
| 10113 // If at a local scope mark the local scope as passed. | 10496 // If at a local scope mark the local scope as passed. |
| 10114 if (at_local_) { | 10497 if (at_local_) { |
| 10115 at_local_ = false; | 10498 at_local_ = false; |
| 10116 local_done_ = true; | 10499 local_done_ = true; |
| 10117 | 10500 |
| 10118 // If the current context is not associated with the local scope the | 10501 // If the current context is not associated with the local scope the |
| 10119 // current context is the next real scope, so don't move to the next | 10502 // current context is the next real scope, so don't move to the next |
| 10120 // context in this case. | 10503 // context in this case. |
| 10121 if (context_->closure() != *function_) { | 10504 if (context_->closure() != *function_) { |
| 10122 return; | 10505 return; |
| 10123 } | 10506 } |
| 10124 } | 10507 } |
| 10125 | 10508 |
| 10126 // The global scope is always the last in the chain. | 10509 // The global scope is always the last in the chain. |
| 10127 if (context_->IsGlobalContext()) { | 10510 if (context_->IsGlobalContext()) { |
| 10128 context_ = Handle<Context>(); | 10511 context_ = Handle<Context>(); |
| 10129 return; | 10512 return; |
| 10130 } | 10513 } |
| 10131 | 10514 |
| 10132 // Move to the next context. | 10515 // Move to the next context. |
| 10133 if (context_->is_function_context()) { | 10516 context_ = Handle<Context>(context_->previous(), isolate_); |
| 10134 context_ = Handle<Context>(Context::cast(context_->closure()->context())); | |
| 10135 } else { | |
| 10136 context_ = Handle<Context>(context_->previous()); | |
| 10137 } | |
| 10138 | 10517 |
| 10139 // If passing the local scope indicate that the current scope is now the | 10518 // If passing the local scope indicate that the current scope is now the |
| 10140 // local scope. | 10519 // local scope. |
| 10141 if (!local_done_ && | 10520 if (!local_done_ && |
| 10142 (context_->IsGlobalContext() || (context_->is_function_context()))) { | 10521 (context_->IsGlobalContext() || context_->IsFunctionContext())) { |
| 10143 at_local_ = true; | 10522 at_local_ = true; |
| 10144 } | 10523 } |
| 10145 } | 10524 } |
| 10146 | 10525 |
| 10147 // Return the type of the current scope. | 10526 // Return the type of the current scope. |
| 10148 int Type() { | 10527 int Type() { |
| 10149 if (at_local_) { | 10528 if (at_local_) { |
| 10150 return ScopeTypeLocal; | 10529 return ScopeTypeLocal; |
| 10151 } | 10530 } |
| 10152 if (context_->IsGlobalContext()) { | 10531 if (context_->IsGlobalContext()) { |
| 10153 ASSERT(context_->global()->IsGlobalObject()); | 10532 ASSERT(context_->global()->IsGlobalObject()); |
| 10154 return ScopeTypeGlobal; | 10533 return ScopeTypeGlobal; |
| 10155 } | 10534 } |
| 10156 if (context_->is_function_context()) { | 10535 if (context_->IsFunctionContext()) { |
| 10157 return ScopeTypeClosure; | 10536 return ScopeTypeClosure; |
| 10158 } | 10537 } |
| 10159 ASSERT(context_->has_extension()); | 10538 if (context_->IsCatchContext()) { |
| 10160 // Current scope is either an explicit with statement or a with statement | |
| 10161 // implicitely generated for a catch block. | |
| 10162 // If the extension object here is a JSContextExtensionObject then | |
| 10163 // current with statement is one frome a catch block otherwise it's a | |
| 10164 // regular with statement. | |
| 10165 if (context_->extension()->IsJSContextExtensionObject()) { | |
| 10166 return ScopeTypeCatch; | 10539 return ScopeTypeCatch; |
| 10167 } | 10540 } |
| 10541 ASSERT(context_->IsWithContext()); |
| 10168 return ScopeTypeWith; | 10542 return ScopeTypeWith; |
| 10169 } | 10543 } |
| 10170 | 10544 |
| 10171 // Return the JavaScript object with the content of the current scope. | 10545 // Return the JavaScript object with the content of the current scope. |
| 10172 Handle<JSObject> ScopeObject() { | 10546 Handle<JSObject> ScopeObject() { |
| 10173 switch (Type()) { | 10547 switch (Type()) { |
| 10174 case ScopeIterator::ScopeTypeGlobal: | 10548 case ScopeIterator::ScopeTypeGlobal: |
| 10175 return Handle<JSObject>(CurrentContext()->global()); | 10549 return Handle<JSObject>(CurrentContext()->global()); |
| 10176 break; | |
| 10177 case ScopeIterator::ScopeTypeLocal: | 10550 case ScopeIterator::ScopeTypeLocal: |
| 10178 // Materialize the content of the local scope into a JSObject. | 10551 // Materialize the content of the local scope into a JSObject. |
| 10179 return MaterializeLocalScope(isolate_, frame_); | 10552 return MaterializeLocalScope(isolate_, frame_); |
| 10180 break; | |
| 10181 case ScopeIterator::ScopeTypeWith: | 10553 case ScopeIterator::ScopeTypeWith: |
| 10554 // Return the with object. |
| 10555 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); |
| 10182 case ScopeIterator::ScopeTypeCatch: | 10556 case ScopeIterator::ScopeTypeCatch: |
| 10183 // Return the with object. | 10557 return MaterializeCatchScope(isolate_, CurrentContext()); |
| 10184 return Handle<JSObject>(CurrentContext()->extension()); | |
| 10185 break; | |
| 10186 case ScopeIterator::ScopeTypeClosure: | 10558 case ScopeIterator::ScopeTypeClosure: |
| 10187 // Materialize the content of the closure scope into a JSObject. | 10559 // Materialize the content of the closure scope into a JSObject. |
| 10188 return MaterializeClosure(isolate_, CurrentContext()); | 10560 return MaterializeClosure(isolate_, CurrentContext()); |
| 10189 break; | |
| 10190 } | 10561 } |
| 10191 UNREACHABLE(); | 10562 UNREACHABLE(); |
| 10192 return Handle<JSObject>(); | 10563 return Handle<JSObject>(); |
| 10193 } | 10564 } |
| 10194 | 10565 |
| 10195 // Return the context for this scope. For the local context there might not | 10566 // Return the context for this scope. For the local context there might not |
| 10196 // be an actual context. | 10567 // be an actual context. |
| 10197 Handle<Context> CurrentContext() { | 10568 Handle<Context> CurrentContext() { |
| 10198 if (at_local_ && context_->closure() != *function_) { | 10569 if (at_local_ && context_->closure() != *function_) { |
| 10199 return Handle<Context>(); | 10570 return Handle<Context>(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 10210 CurrentContext()->Print(); | 10581 CurrentContext()->Print(); |
| 10211 break; | 10582 break; |
| 10212 | 10583 |
| 10213 case ScopeIterator::ScopeTypeLocal: { | 10584 case ScopeIterator::ScopeTypeLocal: { |
| 10214 PrintF("Local:\n"); | 10585 PrintF("Local:\n"); |
| 10215 ScopeInfo<> scope_info(function_->shared()->scope_info()); | 10586 ScopeInfo<> scope_info(function_->shared()->scope_info()); |
| 10216 scope_info.Print(); | 10587 scope_info.Print(); |
| 10217 if (!CurrentContext().is_null()) { | 10588 if (!CurrentContext().is_null()) { |
| 10218 CurrentContext()->Print(); | 10589 CurrentContext()->Print(); |
| 10219 if (CurrentContext()->has_extension()) { | 10590 if (CurrentContext()->has_extension()) { |
| 10220 Handle<JSObject> extension = | 10591 Handle<Object> extension(CurrentContext()->extension()); |
| 10221 Handle<JSObject>(CurrentContext()->extension()); | |
| 10222 if (extension->IsJSContextExtensionObject()) { | 10592 if (extension->IsJSContextExtensionObject()) { |
| 10223 extension->Print(); | 10593 extension->Print(); |
| 10224 } | 10594 } |
| 10225 } | 10595 } |
| 10226 } | 10596 } |
| 10227 break; | 10597 break; |
| 10228 } | 10598 } |
| 10229 | 10599 |
| 10230 case ScopeIterator::ScopeTypeWith: { | 10600 case ScopeIterator::ScopeTypeWith: |
| 10231 PrintF("With:\n"); | 10601 PrintF("With:\n"); |
| 10232 Handle<JSObject> extension = | 10602 CurrentContext()->extension()->Print(); |
| 10233 Handle<JSObject>(CurrentContext()->extension()); | |
| 10234 extension->Print(); | |
| 10235 break; | 10603 break; |
| 10236 } | |
| 10237 | 10604 |
| 10238 case ScopeIterator::ScopeTypeCatch: { | 10605 case ScopeIterator::ScopeTypeCatch: |
| 10239 PrintF("Catch:\n"); | 10606 PrintF("Catch:\n"); |
| 10240 Handle<JSObject> extension = | 10607 CurrentContext()->extension()->Print(); |
| 10241 Handle<JSObject>(CurrentContext()->extension()); | 10608 CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print(); |
| 10242 extension->Print(); | |
| 10243 break; | 10609 break; |
| 10244 } | |
| 10245 | 10610 |
| 10246 case ScopeIterator::ScopeTypeClosure: { | 10611 case ScopeIterator::ScopeTypeClosure: |
| 10247 PrintF("Closure:\n"); | 10612 PrintF("Closure:\n"); |
| 10248 CurrentContext()->Print(); | 10613 CurrentContext()->Print(); |
| 10249 if (CurrentContext()->has_extension()) { | 10614 if (CurrentContext()->has_extension()) { |
| 10250 Handle<JSObject> extension = | 10615 Handle<Object> extension(CurrentContext()->extension()); |
| 10251 Handle<JSObject>(CurrentContext()->extension()); | |
| 10252 if (extension->IsJSContextExtensionObject()) { | 10616 if (extension->IsJSContextExtensionObject()) { |
| 10253 extension->Print(); | 10617 extension->Print(); |
| 10254 } | 10618 } |
| 10255 } | 10619 } |
| 10256 break; | 10620 break; |
| 10257 } | |
| 10258 | 10621 |
| 10259 default: | 10622 default: |
| 10260 UNREACHABLE(); | 10623 UNREACHABLE(); |
| 10261 } | 10624 } |
| 10262 PrintF("\n"); | 10625 PrintF("\n"); |
| 10263 } | 10626 } |
| 10264 #endif | 10627 #endif |
| 10265 | 10628 |
| 10266 private: | 10629 private: |
| 10267 Isolate* isolate_; | 10630 Isolate* isolate_; |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10718 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) { | 11081 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) { |
| 10719 HandleScope scope(isolate); | 11082 HandleScope scope(isolate); |
| 10720 ASSERT(args.length() == 0); | 11083 ASSERT(args.length() == 0); |
| 10721 isolate->debug()->ClearStepping(); | 11084 isolate->debug()->ClearStepping(); |
| 10722 return isolate->heap()->undefined_value(); | 11085 return isolate->heap()->undefined_value(); |
| 10723 } | 11086 } |
| 10724 | 11087 |
| 10725 | 11088 |
| 10726 // Creates a copy of the with context chain. The copy of the context chain is | 11089 // Creates a copy of the with context chain. The copy of the context chain is |
| 10727 // is linked to the function context supplied. | 11090 // is linked to the function context supplied. |
| 10728 static Handle<Context> CopyWithContextChain(Handle<Context> context_chain, | 11091 static Handle<Context> CopyWithContextChain(Isolate* isolate, |
| 10729 Handle<Context> function_context) { | 11092 Handle<JSFunction> function, |
| 10730 // At the bottom of the chain. Return the function context to link to. | 11093 Handle<Context> current, |
| 10731 if (context_chain->is_function_context()) { | 11094 Handle<Context> base) { |
| 10732 return function_context; | 11095 // At the end of the chain. Return the base context to link to. |
| 11096 if (current->IsFunctionContext() || current->IsGlobalContext()) { |
| 11097 return base; |
| 10733 } | 11098 } |
| 10734 | 11099 |
| 10735 // Recursively copy the with contexts. | 11100 // Recursively copy the with and catch contexts. |
| 10736 Handle<Context> previous(context_chain->previous()); | 11101 HandleScope scope(isolate); |
| 10737 Handle<JSObject> extension(JSObject::cast(context_chain->extension())); | 11102 Handle<Context> previous(current->previous()); |
| 10738 Handle<Context> context = CopyWithContextChain(previous, function_context); | 11103 Handle<Context> new_previous = |
| 10739 return context->GetIsolate()->factory()->NewWithContext( | 11104 CopyWithContextChain(isolate, function, previous, base); |
| 10740 context, extension, context_chain->IsCatchContext()); | 11105 Handle<Context> new_current; |
| 11106 if (current->IsCatchContext()) { |
| 11107 Handle<String> name(String::cast(current->extension())); |
| 11108 Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX)); |
| 11109 new_current = |
| 11110 isolate->factory()->NewCatchContext(function, |
| 11111 new_previous, |
| 11112 name, |
| 11113 thrown_object); |
| 11114 } else { |
| 11115 Handle<JSObject> extension(JSObject::cast(current->extension())); |
| 11116 new_current = |
| 11117 isolate->factory()->NewWithContext(function, new_previous, extension); |
| 11118 } |
| 11119 return scope.CloseAndEscape(new_current); |
| 10741 } | 11120 } |
| 10742 | 11121 |
| 10743 | 11122 |
| 10744 // Helper function to find or create the arguments object for | 11123 // Helper function to find or create the arguments object for |
| 10745 // Runtime_DebugEvaluate. | 11124 // Runtime_DebugEvaluate. |
| 10746 static Handle<Object> GetArgumentsObject(Isolate* isolate, | 11125 static Handle<Object> GetArgumentsObject(Isolate* isolate, |
| 10747 JavaScriptFrame* frame, | 11126 JavaScriptFrame* frame, |
| 10748 Handle<JSFunction> function, | 11127 Handle<JSFunction> function, |
| 10749 Handle<SerializedScopeInfo> scope_info, | 11128 Handle<SerializedScopeInfo> scope_info, |
| 10750 const ScopeInfo<>* sinfo, | 11129 const ScopeInfo<>* sinfo, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10858 RETURN_IF_EMPTY_HANDLE(isolate, local_scope); | 11237 RETURN_IF_EMPTY_HANDLE(isolate, local_scope); |
| 10859 | 11238 |
| 10860 // Allocate a new context for the debug evaluation and set the extension | 11239 // Allocate a new context for the debug evaluation and set the extension |
| 10861 // object build. | 11240 // object build. |
| 10862 Handle<Context> context = | 11241 Handle<Context> context = |
| 10863 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, | 11242 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, |
| 10864 go_between); | 11243 go_between); |
| 10865 context->set_extension(*local_scope); | 11244 context->set_extension(*local_scope); |
| 10866 // Copy any with contexts present and chain them in front of this context. | 11245 // Copy any with contexts present and chain them in front of this context. |
| 10867 Handle<Context> frame_context(Context::cast(frame->context())); | 11246 Handle<Context> frame_context(Context::cast(frame->context())); |
| 10868 Handle<Context> function_context(frame_context->fcontext()); | 11247 Handle<Context> function_context(frame_context->declaration_context()); |
| 10869 context = CopyWithContextChain(frame_context, context); | 11248 context = CopyWithContextChain(isolate, go_between, frame_context, context); |
| 10870 | 11249 |
| 10871 if (additional_context->IsJSObject()) { | 11250 if (additional_context->IsJSObject()) { |
| 10872 context = isolate->factory()->NewWithContext(context, | 11251 Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); |
| 10873 Handle<JSObject>::cast(additional_context), false); | 11252 context = |
| 11253 isolate->factory()->NewWithContext(go_between, context, extension); |
| 10874 } | 11254 } |
| 10875 | 11255 |
| 10876 // Wrap the evaluation statement in a new function compiled in the newly | 11256 // Wrap the evaluation statement in a new function compiled in the newly |
| 10877 // created context. The function has one parameter which has to be called | 11257 // created context. The function has one parameter which has to be called |
| 10878 // 'arguments'. This it to have access to what would have been 'arguments' in | 11258 // 'arguments'. This it to have access to what would have been 'arguments' in |
| 10879 // the function being debugged. | 11259 // the function being debugged. |
| 10880 // function(arguments,__source__) {return eval(__source__);} | 11260 // function(arguments,__source__) {return eval(__source__);} |
| 10881 | 11261 |
| 10882 Handle<String> function_source = | 11262 Handle<String> function_source = |
| 10883 isolate->factory()->NewStringFromAscii( | 11263 isolate->factory()->NewStringFromAscii( |
| (...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11620 return LiveObjectList::Capture(); | 12000 return LiveObjectList::Capture(); |
| 11621 #else | 12001 #else |
| 11622 return isolate->heap()->undefined_value(); | 12002 return isolate->heap()->undefined_value(); |
| 11623 #endif | 12003 #endif |
| 11624 } | 12004 } |
| 11625 | 12005 |
| 11626 | 12006 |
| 11627 // Deletes the specified live object list. | 12007 // Deletes the specified live object list. |
| 11628 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) { | 12008 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteLOL) { |
| 11629 #ifdef LIVE_OBJECT_LIST | 12009 #ifdef LIVE_OBJECT_LIST |
| 11630 CONVERT_SMI_CHECKED(id, args[0]); | 12010 CONVERT_SMI_ARG_CHECKED(id, 0); |
| 11631 bool success = LiveObjectList::Delete(id); | 12011 bool success = LiveObjectList::Delete(id); |
| 11632 return success ? isolate->heap()->true_value() : | 12012 return success ? isolate->heap()->true_value() : |
| 11633 isolate->heap()->false_value(); | 12013 isolate->heap()->false_value(); |
| 11634 #else | 12014 #else |
| 11635 return isolate->heap()->undefined_value(); | 12015 return isolate->heap()->undefined_value(); |
| 11636 #endif | 12016 #endif |
| 11637 } | 12017 } |
| 11638 | 12018 |
| 11639 | 12019 |
| 11640 // Generates the response to a debugger request for a dump of the objects | 12020 // Generates the response to a debugger request for a dump of the objects |
| 11641 // contained in the difference between the captured live object lists | 12021 // contained in the difference between the captured live object lists |
| 11642 // specified by id1 and id2. | 12022 // specified by id1 and id2. |
| 11643 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be | 12023 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be |
| 11644 // dumped. | 12024 // dumped. |
| 11645 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) { | 12025 RUNTIME_FUNCTION(MaybeObject*, Runtime_DumpLOL) { |
| 11646 #ifdef LIVE_OBJECT_LIST | 12026 #ifdef LIVE_OBJECT_LIST |
| 11647 HandleScope scope; | 12027 HandleScope scope; |
| 11648 CONVERT_SMI_CHECKED(id1, args[0]); | 12028 CONVERT_SMI_ARG_CHECKED(id1, 0); |
| 11649 CONVERT_SMI_CHECKED(id2, args[1]); | 12029 CONVERT_SMI_ARG_CHECKED(id2, 1); |
| 11650 CONVERT_SMI_CHECKED(start, args[2]); | 12030 CONVERT_SMI_ARG_CHECKED(start, 2); |
| 11651 CONVERT_SMI_CHECKED(count, args[3]); | 12031 CONVERT_SMI_ARG_CHECKED(count, 3); |
| 11652 CONVERT_ARG_CHECKED(JSObject, filter_obj, 4); | 12032 CONVERT_ARG_CHECKED(JSObject, filter_obj, 4); |
| 11653 EnterDebugger enter_debugger; | 12033 EnterDebugger enter_debugger; |
| 11654 return LiveObjectList::Dump(id1, id2, start, count, filter_obj); | 12034 return LiveObjectList::Dump(id1, id2, start, count, filter_obj); |
| 11655 #else | 12035 #else |
| 11656 return isolate->heap()->undefined_value(); | 12036 return isolate->heap()->undefined_value(); |
| 11657 #endif | 12037 #endif |
| 11658 } | 12038 } |
| 11659 | 12039 |
| 11660 | 12040 |
| 11661 // Gets the specified object as requested by the debugger. | 12041 // Gets the specified object as requested by the debugger. |
| 11662 // This is only used for obj ids shown in live object lists. | 12042 // This is only used for obj ids shown in live object lists. |
| 11663 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) { | 12043 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObj) { |
| 11664 #ifdef LIVE_OBJECT_LIST | 12044 #ifdef LIVE_OBJECT_LIST |
| 11665 CONVERT_SMI_CHECKED(obj_id, args[0]); | 12045 CONVERT_SMI_ARG_CHECKED(obj_id, 0); |
| 11666 Object* result = LiveObjectList::GetObj(obj_id); | 12046 Object* result = LiveObjectList::GetObj(obj_id); |
| 11667 return result; | 12047 return result; |
| 11668 #else | 12048 #else |
| 11669 return isolate->heap()->undefined_value(); | 12049 return isolate->heap()->undefined_value(); |
| 11670 #endif | 12050 #endif |
| 11671 } | 12051 } |
| 11672 | 12052 |
| 11673 | 12053 |
| 11674 // Gets the obj id for the specified address if valid. | 12054 // Gets the obj id for the specified address if valid. |
| 11675 // This is only used for obj ids shown in live object lists. | 12055 // This is only used for obj ids shown in live object lists. |
| 11676 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) { | 12056 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjId) { |
| 11677 #ifdef LIVE_OBJECT_LIST | 12057 #ifdef LIVE_OBJECT_LIST |
| 11678 HandleScope scope; | 12058 HandleScope scope; |
| 11679 CONVERT_ARG_CHECKED(String, address, 0); | 12059 CONVERT_ARG_CHECKED(String, address, 0); |
| 11680 Object* result = LiveObjectList::GetObjId(address); | 12060 Object* result = LiveObjectList::GetObjId(address); |
| 11681 return result; | 12061 return result; |
| 11682 #else | 12062 #else |
| 11683 return isolate->heap()->undefined_value(); | 12063 return isolate->heap()->undefined_value(); |
| 11684 #endif | 12064 #endif |
| 11685 } | 12065 } |
| 11686 | 12066 |
| 11687 | 12067 |
| 11688 // Gets the retainers that references the specified object alive. | 12068 // Gets the retainers that references the specified object alive. |
| 11689 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) { | 12069 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLObjRetainers) { |
| 11690 #ifdef LIVE_OBJECT_LIST | 12070 #ifdef LIVE_OBJECT_LIST |
| 11691 HandleScope scope; | 12071 HandleScope scope; |
| 11692 CONVERT_SMI_CHECKED(obj_id, args[0]); | 12072 CONVERT_SMI_ARG_CHECKED(obj_id, 0); |
| 11693 RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject()); | 12073 RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject()); |
| 11694 RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean()); | 12074 RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean()); |
| 11695 RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi()); | 12075 RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi()); |
| 11696 RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi()); | 12076 RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi()); |
| 11697 CONVERT_ARG_CHECKED(JSObject, filter_obj, 5); | 12077 CONVERT_ARG_CHECKED(JSObject, filter_obj, 5); |
| 11698 | 12078 |
| 11699 Handle<JSObject> instance_filter; | 12079 Handle<JSObject> instance_filter; |
| 11700 if (args[1]->IsJSObject()) { | 12080 if (args[1]->IsJSObject()) { |
| 11701 instance_filter = args.at<JSObject>(1); | 12081 instance_filter = args.at<JSObject>(1); |
| 11702 } | 12082 } |
| 11703 bool verbose = false; | 12083 bool verbose = false; |
| 11704 if (args[2]->IsBoolean()) { | 12084 if (args[2]->IsBoolean()) { |
| 11705 verbose = args[2]->IsTrue(); | 12085 verbose = args[2]->IsTrue(); |
| 11706 } | 12086 } |
| 11707 int start = 0; | 12087 int start = 0; |
| 11708 if (args[3]->IsSmi()) { | 12088 if (args[3]->IsSmi()) { |
| 11709 start = Smi::cast(args[3])->value(); | 12089 start = args.smi_at(3); |
| 11710 } | 12090 } |
| 11711 int limit = Smi::kMaxValue; | 12091 int limit = Smi::kMaxValue; |
| 11712 if (args[4]->IsSmi()) { | 12092 if (args[4]->IsSmi()) { |
| 11713 limit = Smi::cast(args[4])->value(); | 12093 limit = args.smi_at(4); |
| 11714 } | 12094 } |
| 11715 | 12095 |
| 11716 return LiveObjectList::GetObjRetainers(obj_id, | 12096 return LiveObjectList::GetObjRetainers(obj_id, |
| 11717 instance_filter, | 12097 instance_filter, |
| 11718 verbose, | 12098 verbose, |
| 11719 start, | 12099 start, |
| 11720 limit, | 12100 limit, |
| 11721 filter_obj); | 12101 filter_obj); |
| 11722 #else | 12102 #else |
| 11723 return isolate->heap()->undefined_value(); | 12103 return isolate->heap()->undefined_value(); |
| 11724 #endif | 12104 #endif |
| 11725 } | 12105 } |
| 11726 | 12106 |
| 11727 | 12107 |
| 11728 // Gets the reference path between 2 objects. | 12108 // Gets the reference path between 2 objects. |
| 11729 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) { | 12109 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLOLPath) { |
| 11730 #ifdef LIVE_OBJECT_LIST | 12110 #ifdef LIVE_OBJECT_LIST |
| 11731 HandleScope scope; | 12111 HandleScope scope; |
| 11732 CONVERT_SMI_CHECKED(obj_id1, args[0]); | 12112 CONVERT_SMI_ARG_CHECKED(obj_id1, 0); |
| 11733 CONVERT_SMI_CHECKED(obj_id2, args[1]); | 12113 CONVERT_SMI_ARG_CHECKED(obj_id2, 1); |
| 11734 RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject()); | 12114 RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject()); |
| 11735 | 12115 |
| 11736 Handle<JSObject> instance_filter; | 12116 Handle<JSObject> instance_filter; |
| 11737 if (args[2]->IsJSObject()) { | 12117 if (args[2]->IsJSObject()) { |
| 11738 instance_filter = args.at<JSObject>(2); | 12118 instance_filter = args.at<JSObject>(2); |
| 11739 } | 12119 } |
| 11740 | 12120 |
| 11741 Object* result = | 12121 Object* result = |
| 11742 LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter); | 12122 LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter); |
| 11743 return result; | 12123 return result; |
| 11744 #else | 12124 #else |
| 11745 return isolate->heap()->undefined_value(); | 12125 return isolate->heap()->undefined_value(); |
| 11746 #endif | 12126 #endif |
| 11747 } | 12127 } |
| 11748 | 12128 |
| 11749 | 12129 |
| 11750 // Generates the response to a debugger request for a list of all | 12130 // Generates the response to a debugger request for a list of all |
| 11751 // previously captured live object lists. | 12131 // previously captured live object lists. |
| 11752 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) { | 12132 RUNTIME_FUNCTION(MaybeObject*, Runtime_InfoLOL) { |
| 11753 #ifdef LIVE_OBJECT_LIST | 12133 #ifdef LIVE_OBJECT_LIST |
| 11754 CONVERT_SMI_CHECKED(start, args[0]); | 12134 CONVERT_SMI_ARG_CHECKED(start, 0); |
| 11755 CONVERT_SMI_CHECKED(count, args[1]); | 12135 CONVERT_SMI_ARG_CHECKED(count, 1); |
| 11756 return LiveObjectList::Info(start, count); | 12136 return LiveObjectList::Info(start, count); |
| 11757 #else | 12137 #else |
| 11758 return isolate->heap()->undefined_value(); | 12138 return isolate->heap()->undefined_value(); |
| 11759 #endif | 12139 #endif |
| 11760 } | 12140 } |
| 11761 | 12141 |
| 11762 | 12142 |
| 11763 // Gets a dump of the specified object as requested by the debugger. | 12143 // Gets a dump of the specified object as requested by the debugger. |
| 11764 // This is only used for obj ids shown in live object lists. | 12144 // This is only used for obj ids shown in live object lists. |
| 11765 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) { | 12145 RUNTIME_FUNCTION(MaybeObject*, Runtime_PrintLOLObj) { |
| 11766 #ifdef LIVE_OBJECT_LIST | 12146 #ifdef LIVE_OBJECT_LIST |
| 11767 HandleScope scope; | 12147 HandleScope scope; |
| 11768 CONVERT_SMI_CHECKED(obj_id, args[0]); | 12148 CONVERT_SMI_ARG_CHECKED(obj_id, 0); |
| 11769 Object* result = LiveObjectList::PrintObj(obj_id); | 12149 Object* result = LiveObjectList::PrintObj(obj_id); |
| 11770 return result; | 12150 return result; |
| 11771 #else | 12151 #else |
| 11772 return isolate->heap()->undefined_value(); | 12152 return isolate->heap()->undefined_value(); |
| 11773 #endif | 12153 #endif |
| 11774 } | 12154 } |
| 11775 | 12155 |
| 11776 | 12156 |
| 11777 // Resets and releases all previously captured live object lists. | 12157 // Resets and releases all previously captured live object lists. |
| 11778 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) { | 12158 RUNTIME_FUNCTION(MaybeObject*, Runtime_ResetLOL) { |
| 11779 #ifdef LIVE_OBJECT_LIST | 12159 #ifdef LIVE_OBJECT_LIST |
| 11780 LiveObjectList::Reset(); | 12160 LiveObjectList::Reset(); |
| 11781 return isolate->heap()->undefined_value(); | 12161 return isolate->heap()->undefined_value(); |
| 11782 #else | 12162 #else |
| 11783 return isolate->heap()->undefined_value(); | 12163 return isolate->heap()->undefined_value(); |
| 11784 #endif | 12164 #endif |
| 11785 } | 12165 } |
| 11786 | 12166 |
| 11787 | 12167 |
| 11788 // Generates the response to a debugger request for a summary of the types | 12168 // Generates the response to a debugger request for a summary of the types |
| 11789 // of objects in the difference between the captured live object lists | 12169 // of objects in the difference between the captured live object lists |
| 11790 // specified by id1 and id2. | 12170 // specified by id1 and id2. |
| 11791 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be | 12171 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be |
| 11792 // summarized. | 12172 // summarized. |
| 11793 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) { | 12173 RUNTIME_FUNCTION(MaybeObject*, Runtime_SummarizeLOL) { |
| 11794 #ifdef LIVE_OBJECT_LIST | 12174 #ifdef LIVE_OBJECT_LIST |
| 11795 HandleScope scope; | 12175 HandleScope scope; |
| 11796 CONVERT_SMI_CHECKED(id1, args[0]); | 12176 CONVERT_SMI_ARG_CHECKED(id1, 0); |
| 11797 CONVERT_SMI_CHECKED(id2, args[1]); | 12177 CONVERT_SMI_ARG_CHECKED(id2, 1); |
| 11798 CONVERT_ARG_CHECKED(JSObject, filter_obj, 2); | 12178 CONVERT_ARG_CHECKED(JSObject, filter_obj, 2); |
| 11799 | 12179 |
| 11800 EnterDebugger enter_debugger; | 12180 EnterDebugger enter_debugger; |
| 11801 return LiveObjectList::Summarize(id1, id2, filter_obj); | 12181 return LiveObjectList::Summarize(id1, id2, filter_obj); |
| 11802 #else | 12182 #else |
| 11803 return isolate->heap()->undefined_value(); | 12183 return isolate->heap()->undefined_value(); |
| 11804 #endif | 12184 #endif |
| 11805 } | 12185 } |
| 11806 | 12186 |
| 11807 #endif // ENABLE_DEBUGGER_SUPPORT | 12187 #endif // ENABLE_DEBUGGER_SUPPORT |
| 11808 | 12188 |
| 11809 | 12189 |
| 11810 #ifdef ENABLE_LOGGING_AND_PROFILING | 12190 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 11811 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) { | 12191 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerResume) { |
| 11812 NoHandleAllocation ha; | 12192 NoHandleAllocation ha; |
| 11813 ASSERT(args.length() == 2); | 12193 v8::V8::ResumeProfiler(); |
| 11814 | |
| 11815 CONVERT_CHECKED(Smi, smi_modules, args[0]); | |
| 11816 CONVERT_CHECKED(Smi, smi_tag, args[1]); | |
| 11817 v8::V8::ResumeProfilerEx(smi_modules->value(), smi_tag->value()); | |
| 11818 return isolate->heap()->undefined_value(); | 12194 return isolate->heap()->undefined_value(); |
| 11819 } | 12195 } |
| 11820 | 12196 |
| 11821 | 12197 |
| 11822 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) { | 12198 RUNTIME_FUNCTION(MaybeObject*, Runtime_ProfilerPause) { |
| 11823 NoHandleAllocation ha; | 12199 NoHandleAllocation ha; |
| 11824 ASSERT(args.length() == 2); | 12200 v8::V8::PauseProfiler(); |
| 11825 | |
| 11826 CONVERT_CHECKED(Smi, smi_modules, args[0]); | |
| 11827 CONVERT_CHECKED(Smi, smi_tag, args[1]); | |
| 11828 v8::V8::PauseProfilerEx(smi_modules->value(), smi_tag->value()); | |
| 11829 return isolate->heap()->undefined_value(); | 12201 return isolate->heap()->undefined_value(); |
| 11830 } | 12202 } |
| 11831 | 12203 |
| 11832 #endif // ENABLE_LOGGING_AND_PROFILING | 12204 #endif // ENABLE_LOGGING_AND_PROFILING |
| 11833 | 12205 |
| 11834 // Finds the script object from the script data. NOTE: This operation uses | 12206 // Finds the script object from the script data. NOTE: This operation uses |
| 11835 // heap traversal to find the function generated for the source position | 12207 // heap traversal to find the function generated for the source position |
| 11836 // for the requested break point. For lazily compiled functions several heap | 12208 // for the requested break point. For lazily compiled functions several heap |
| 11837 // traversals might be required rendering this operation as a rather slow | 12209 // traversals might be required rendering this operation as a rather slow |
| 11838 // operation. However for setting break points which is normally done through | 12210 // operation. However for setting break points which is normally done through |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11978 | 12350 |
| 11979 const char* version_string = v8::V8::GetVersion(); | 12351 const char* version_string = v8::V8::GetVersion(); |
| 11980 | 12352 |
| 11981 return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string), | 12353 return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string), |
| 11982 NOT_TENURED); | 12354 NOT_TENURED); |
| 11983 } | 12355 } |
| 11984 | 12356 |
| 11985 | 12357 |
| 11986 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) { | 12358 RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) { |
| 11987 ASSERT(args.length() == 2); | 12359 ASSERT(args.length() == 2); |
| 11988 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) + | 12360 OS::PrintError("abort: %s\n", |
| 11989 Smi::cast(args[1])->value()); | 12361 reinterpret_cast<char*>(args[0]) + args.smi_at(1)); |
| 11990 isolate->PrintStack(); | 12362 isolate->PrintStack(); |
| 11991 OS::Abort(); | 12363 OS::Abort(); |
| 11992 UNREACHABLE(); | 12364 UNREACHABLE(); |
| 11993 return NULL; | 12365 return NULL; |
| 11994 } | 12366 } |
| 11995 | 12367 |
| 11996 | 12368 |
| 11997 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) { | 12369 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) { |
| 11998 // This is only called from codegen, so checks might be more lax. | 12370 // This is only called from codegen, so checks might be more lax. |
| 11999 CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]); | 12371 CONVERT_CHECKED(JSFunctionResultCache, cache, args[0]); |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12181 return isolate->heap()->undefined_value(); | 12553 return isolate->heap()->undefined_value(); |
| 12182 } | 12554 } |
| 12183 | 12555 |
| 12184 | 12556 |
| 12185 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) { | 12557 RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) { |
| 12186 UNREACHABLE(); // implemented as macro in the parser | 12558 UNREACHABLE(); // implemented as macro in the parser |
| 12187 return NULL; | 12559 return NULL; |
| 12188 } | 12560 } |
| 12189 | 12561 |
| 12190 | 12562 |
| 12563 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name) \ |
| 12564 RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) { \ |
| 12565 CONVERT_CHECKED(JSObject, obj, args[0]); \ |
| 12566 return isolate->heap()->ToBoolean(obj->Has##Name()); \ |
| 12567 } |
| 12568 |
| 12569 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastElements) |
| 12570 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements) |
| 12571 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements) |
| 12572 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements) |
| 12573 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements) |
| 12574 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements) |
| 12575 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements) |
| 12576 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements) |
| 12577 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements) |
| 12578 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements) |
| 12579 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements) |
| 12580 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements) |
| 12581 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements) |
| 12582 |
| 12583 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION |
| 12584 |
| 12191 // ---------------------------------------------------------------------------- | 12585 // ---------------------------------------------------------------------------- |
| 12192 // Implementation of Runtime | 12586 // Implementation of Runtime |
| 12193 | 12587 |
| 12194 #define F(name, number_of_args, result_size) \ | 12588 #define F(name, number_of_args, result_size) \ |
| 12195 { Runtime::k##name, Runtime::RUNTIME, #name, \ | 12589 { Runtime::k##name, Runtime::RUNTIME, #name, \ |
| 12196 FUNCTION_ADDR(Runtime_##name), number_of_args, result_size }, | 12590 FUNCTION_ADDR(Runtime_##name), number_of_args, result_size }, |
| 12197 | 12591 |
| 12198 | 12592 |
| 12199 #define I(name, number_of_args, result_size) \ | 12593 #define I(name, number_of_args, result_size) \ |
| 12200 { Runtime::kInline##name, Runtime::INLINE, \ | 12594 { Runtime::kInline##name, Runtime::INLINE, \ |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12264 } else { | 12658 } else { |
| 12265 // Handle last resort GC and make sure to allow future allocations | 12659 // Handle last resort GC and make sure to allow future allocations |
| 12266 // to grow the heap without causing GCs (if possible). | 12660 // to grow the heap without causing GCs (if possible). |
| 12267 isolate->counters()->gc_last_resort_from_js()->Increment(); | 12661 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 12268 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); | 12662 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
| 12269 } | 12663 } |
| 12270 } | 12664 } |
| 12271 | 12665 |
| 12272 | 12666 |
| 12273 } } // namespace v8::internal | 12667 } } // namespace v8::internal |
| OLD | NEW |