| 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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 &done, | 144 &done, |
| 145 receiver, | 145 receiver, |
| 146 properties, | 146 properties, |
| 147 name, | 147 name, |
| 148 scratch1); | 148 scratch1); |
| 149 __ bind(&done); | 149 __ bind(&done); |
| 150 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | 150 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); |
| 151 } | 151 } |
| 152 | 152 |
| 153 | 153 |
| 154 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 155 // handlified. | |
| 156 MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( | |
| 157 MacroAssembler* masm, | |
| 158 Label* miss_label, | |
| 159 Register receiver, | |
| 160 String* name, | |
| 161 Register scratch0, | |
| 162 Register scratch1) { | |
| 163 ASSERT(name->IsSymbol()); | |
| 164 Counters* counters = masm->isolate()->counters(); | |
| 165 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); | |
| 166 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | |
| 167 | |
| 168 Label done; | |
| 169 | |
| 170 const int kInterceptorOrAccessCheckNeededMask = | |
| 171 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | |
| 172 | |
| 173 // Bail out if the receiver has a named interceptor or requires access checks. | |
| 174 Register map = scratch1; | |
| 175 __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
| 176 __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | |
| 177 __ And(at, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | |
| 178 __ Branch(miss_label, ne, at, Operand(zero_reg)); | |
| 179 | |
| 180 | |
| 181 // Check that receiver is a JSObject. | |
| 182 __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | |
| 183 __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
| 184 | |
| 185 // Load properties array. | |
| 186 Register properties = scratch0; | |
| 187 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 188 // Check that the properties array is a dictionary. | |
| 189 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | |
| 190 Register tmp = properties; | |
| 191 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | |
| 192 __ Branch(miss_label, ne, map, Operand(tmp)); | |
| 193 | |
| 194 // Restore the temporarily used register. | |
| 195 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 196 | |
| 197 MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( | |
| 198 masm, | |
| 199 miss_label, | |
| 200 &done, | |
| 201 receiver, | |
| 202 properties, | |
| 203 name, | |
| 204 scratch1); | |
| 205 if (result->IsFailure()) return result; | |
| 206 | |
| 207 __ bind(&done); | |
| 208 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); | |
| 209 | |
| 210 return result; | |
| 211 } | |
| 212 | |
| 213 | |
| 214 void StubCache::GenerateProbe(MacroAssembler* masm, | 154 void StubCache::GenerateProbe(MacroAssembler* masm, |
| 215 Code::Flags flags, | 155 Code::Flags flags, |
| 216 Register receiver, | 156 Register receiver, |
| 217 Register name, | 157 Register name, |
| 218 Register scratch, | 158 Register scratch, |
| 219 Register extra, | 159 Register extra, |
| 220 Register extra2) { | 160 Register extra2) { |
| 221 Isolate* isolate = masm->isolate(); | 161 Isolate* isolate = masm->isolate(); |
| 222 Label miss; | 162 Label miss; |
| 223 | 163 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 __ lw(prototype, MemOperand(prototype, Context::SlotOffset(index))); | 227 __ lw(prototype, MemOperand(prototype, Context::SlotOffset(index))); |
| 288 // Load the initial map. The global functions all have initial maps. | 228 // Load the initial map. The global functions all have initial maps. |
| 289 __ lw(prototype, | 229 __ lw(prototype, |
| 290 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | 230 FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); |
| 291 // Load the prototype from the initial map. | 231 // Load the prototype from the initial map. |
| 292 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 232 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 293 } | 233 } |
| 294 | 234 |
| 295 | 235 |
| 296 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 236 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
| 297 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 237 MacroAssembler* masm, |
| 238 int index, |
| 239 Register prototype, |
| 240 Label* miss) { |
| 298 Isolate* isolate = masm->isolate(); | 241 Isolate* isolate = masm->isolate(); |
| 299 // Check we're still in the same context. | 242 // Check we're still in the same context. |
| 300 __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | 243 __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 301 ASSERT(!prototype.is(at)); | 244 ASSERT(!prototype.is(at)); |
| 302 __ li(at, isolate->global()); | 245 __ li(at, isolate->global()); |
| 303 __ Branch(miss, ne, prototype, Operand(at)); | 246 __ Branch(miss, ne, prototype, Operand(at)); |
| 304 // Get the global function with the given index. | 247 // Get the global function with the given index. |
| 305 JSFunction* function = | 248 Handle<JSFunction> function( |
| 306 JSFunction::cast(isolate->global_context()->get(index)); | 249 JSFunction::cast(isolate->global_context()->get(index))); |
| 307 // Load its initial map. The global functions all have initial maps. | 250 // Load its initial map. The global functions all have initial maps. |
| 308 __ li(prototype, Handle<Map>(function->initial_map())); | 251 __ li(prototype, Handle<Map>(function->initial_map())); |
| 309 // Load the prototype from the initial map. | 252 // Load the prototype from the initial map. |
| 310 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); | 253 __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); |
| 311 } | 254 } |
| 312 | 255 |
| 313 | 256 |
| 314 // Load a fast property out of a holder object (src). In-object properties | 257 // Load a fast property out of a holder object (src). In-object properties |
| 315 // are loaded directly otherwise the property is loaded from the properties | 258 // are loaded directly otherwise the property is loaded from the properties |
| 316 // fixed array. | 259 // fixed array. |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 ? CALL_AS_FUNCTION | 501 ? CALL_AS_FUNCTION |
| 559 : CALL_AS_METHOD; | 502 : CALL_AS_METHOD; |
| 560 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | 503 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 561 } | 504 } |
| 562 | 505 |
| 563 | 506 |
| 564 static void PushInterceptorArguments(MacroAssembler* masm, | 507 static void PushInterceptorArguments(MacroAssembler* masm, |
| 565 Register receiver, | 508 Register receiver, |
| 566 Register holder, | 509 Register holder, |
| 567 Register name, | 510 Register name, |
| 568 JSObject* holder_obj) { | 511 Handle<JSObject> holder_obj) { |
| 569 __ push(name); | 512 __ push(name); |
| 570 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 513 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 571 ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor)); | 514 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 572 Register scratch = name; | 515 Register scratch = name; |
| 573 __ li(scratch, Operand(Handle<Object>(interceptor))); | 516 __ li(scratch, Operand(interceptor)); |
| 574 __ Push(scratch, receiver, holder); | 517 __ Push(scratch, receiver, holder); |
| 575 __ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); | 518 __ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); |
| 576 __ push(scratch); | 519 __ push(scratch); |
| 577 } | 520 } |
| 578 | 521 |
| 579 | 522 |
| 580 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 523 static void CompileCallLoadPropertyWithInterceptor( |
| 581 Register receiver, | 524 MacroAssembler* masm, |
| 582 Register holder, | 525 Register receiver, |
| 583 Register name, | 526 Register holder, |
| 584 JSObject* holder_obj) { | 527 Register name, |
| 528 Handle<JSObject> holder_obj) { |
| 585 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 529 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 586 | 530 |
| 587 ExternalReference ref = | 531 ExternalReference ref = |
| 588 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), | 532 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
| 589 masm->isolate()); | 533 masm->isolate()); |
| 590 __ li(a0, Operand(5)); | 534 __ li(a0, Operand(5)); |
| 591 __ li(a1, Operand(ref)); | 535 __ li(a1, Operand(ref)); |
| 592 | 536 |
| 593 CEntryStub stub(1); | 537 CEntryStub stub(1); |
| 594 __ CallStub(&stub); | 538 __ CallStub(&stub); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 610 } | 554 } |
| 611 } | 555 } |
| 612 | 556 |
| 613 | 557 |
| 614 // Undoes the effects of ReserveSpaceForFastApiCall. | 558 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 615 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 559 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
| 616 __ Drop(kFastApiCallArguments); | 560 __ Drop(kFastApiCallArguments); |
| 617 } | 561 } |
| 618 | 562 |
| 619 | 563 |
| 620 static MaybeObject* GenerateFastApiDirectCall( | 564 static void GenerateFastApiDirectCall(MacroAssembler* masm, |
| 621 MacroAssembler* masm, | 565 const CallOptimization& optimization, |
| 622 const CallOptimization& optimization, | 566 int argc) { |
| 623 int argc) { | |
| 624 // ----------- S t a t e ------------- | 567 // ----------- S t a t e ------------- |
| 625 // -- sp[0] : holder (set by CheckPrototypes) | 568 // -- sp[0] : holder (set by CheckPrototypes) |
| 626 // -- sp[4] : callee js function | 569 // -- sp[4] : callee js function |
| 627 // -- sp[8] : call data | 570 // -- sp[8] : call data |
| 628 // -- sp[12] : last js argument | 571 // -- sp[12] : last js argument |
| 629 // -- ... | 572 // -- ... |
| 630 // -- sp[(argc + 3) * 4] : first js argument | 573 // -- sp[(argc + 3) * 4] : first js argument |
| 631 // -- sp[(argc + 4) * 4] : receiver | 574 // -- sp[(argc + 4) * 4] : receiver |
| 632 // ----------------------------------- | 575 // ----------------------------------- |
| 633 // Get the function and setup the context. | 576 // Get the function and setup the context. |
| 634 JSFunction* function = optimization.constant_function(); | 577 Handle<JSFunction> function = optimization.constant_function(); |
| 635 __ li(t1, Operand(Handle<JSFunction>(function))); | 578 __ li(t1, Operand(function)); |
| 636 __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); | 579 __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); |
| 637 | 580 |
| 638 // Pass the additional arguments FastHandleApiCall expects. | 581 // Pass the additional arguments FastHandleApiCall expects. |
| 639 Object* call_data = optimization.api_call_info()->data(); | 582 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); |
| 640 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); | 583 Handle<Object> call_data(api_call_info->data()); |
| 641 if (masm->isolate()->heap()->InNewSpace(call_data)) { | 584 if (masm->isolate()->heap()->InNewSpace(*call_data)) { |
| 642 __ li(a0, api_call_info_handle); | 585 __ li(a0, api_call_info); |
| 643 __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset)); | 586 __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset)); |
| 644 } else { | 587 } else { |
| 645 __ li(t2, Operand(Handle<Object>(call_data))); | 588 __ li(t2, call_data); |
| 646 } | 589 } |
| 647 | 590 |
| 648 // Store js function and call data. | 591 // Store js function and call data. |
| 649 __ sw(t1, MemOperand(sp, 1 * kPointerSize)); | 592 __ sw(t1, MemOperand(sp, 1 * kPointerSize)); |
| 650 __ sw(t2, MemOperand(sp, 2 * kPointerSize)); | 593 __ sw(t2, MemOperand(sp, 2 * kPointerSize)); |
| 651 | 594 |
| 652 // a2 points to call data as expected by Arguments | 595 // a2 points to call data as expected by Arguments |
| 653 // (refer to layout above). | 596 // (refer to layout above). |
| 654 __ Addu(a2, sp, Operand(2 * kPointerSize)); | 597 __ Addu(a2, sp, Operand(2 * kPointerSize)); |
| 655 | 598 |
| 656 Object* callback = optimization.api_call_info()->callback(); | |
| 657 Address api_function_address = v8::ToCData<Address>(callback); | |
| 658 ApiFunction fun(api_function_address); | |
| 659 | |
| 660 const int kApiStackSpace = 4; | 599 const int kApiStackSpace = 4; |
| 661 | 600 |
| 662 FrameScope frame_scope(masm, StackFrame::MANUAL); | 601 FrameScope frame_scope(masm, StackFrame::MANUAL); |
| 663 __ EnterExitFrame(false, kApiStackSpace); | 602 __ EnterExitFrame(false, kApiStackSpace); |
| 664 | 603 |
| 665 // NOTE: the O32 abi requires a0 to hold a special pointer when returning a | 604 // NOTE: the O32 abi requires a0 to hold a special pointer when returning a |
| 666 // struct from the function (which is currently the case). This means we pass | 605 // struct from the function (which is currently the case). This means we pass |
| 667 // the first argument in a1 instead of a0. TryCallApiFunctionAndReturn | 606 // the first argument in a1 instead of a0. TryCallApiFunctionAndReturn |
| 668 // will handle setting up a0. | 607 // will handle setting up a0. |
| 669 | 608 |
| 670 // a1 = v8::Arguments& | 609 // a1 = v8::Arguments& |
| 671 // Arguments is built at sp + 1 (sp is a reserved spot for ra). | 610 // Arguments is built at sp + 1 (sp is a reserved spot for ra). |
| 672 __ Addu(a1, sp, kPointerSize); | 611 __ Addu(a1, sp, kPointerSize); |
| 673 | 612 |
| 674 // v8::Arguments::implicit_args = data | 613 // v8::Arguments::implicit_args = data |
| 675 __ sw(a2, MemOperand(a1, 0 * kPointerSize)); | 614 __ sw(a2, MemOperand(a1, 0 * kPointerSize)); |
| 676 // v8::Arguments::values = last argument | 615 // v8::Arguments::values = last argument |
| 677 __ Addu(t0, a2, Operand(argc * kPointerSize)); | 616 __ Addu(t0, a2, Operand(argc * kPointerSize)); |
| 678 __ sw(t0, MemOperand(a1, 1 * kPointerSize)); | 617 __ sw(t0, MemOperand(a1, 1 * kPointerSize)); |
| 679 // v8::Arguments::length_ = argc | 618 // v8::Arguments::length_ = argc |
| 680 __ li(t0, Operand(argc)); | 619 __ li(t0, Operand(argc)); |
| 681 __ sw(t0, MemOperand(a1, 2 * kPointerSize)); | 620 __ sw(t0, MemOperand(a1, 2 * kPointerSize)); |
| 682 // v8::Arguments::is_construct_call = 0 | 621 // v8::Arguments::is_construct_call = 0 |
| 683 __ sw(zero_reg, MemOperand(a1, 3 * kPointerSize)); | 622 __ sw(zero_reg, MemOperand(a1, 3 * kPointerSize)); |
| 684 | 623 |
| 685 // Emitting a stub call may try to allocate (if the code is not | |
| 686 // already generated). Do not allow the assembler to perform a | |
| 687 // garbage collection but instead return the allocation failure | |
| 688 // object. | |
| 689 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; | 624 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; |
| 625 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
| 626 ApiFunction fun(function_address); |
| 690 ExternalReference ref = | 627 ExternalReference ref = |
| 691 ExternalReference(&fun, | 628 ExternalReference(&fun, |
| 692 ExternalReference::DIRECT_API_CALL, | 629 ExternalReference::DIRECT_API_CALL, |
| 693 masm->isolate()); | 630 masm->isolate()); |
| 694 AllowExternalCallThatCantCauseGC scope(masm); | 631 AllowExternalCallThatCantCauseGC scope(masm); |
| 695 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 632 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 696 } | 633 } |
| 697 | 634 |
| 698 class CallInterceptorCompiler BASE_EMBEDDED { | 635 class CallInterceptorCompiler BASE_EMBEDDED { |
| 699 public: | 636 public: |
| 700 CallInterceptorCompiler(StubCompiler* stub_compiler, | 637 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 701 const ParameterCount& arguments, | 638 const ParameterCount& arguments, |
| 702 Register name, | 639 Register name, |
| 703 Code::ExtraICState extra_ic_state) | 640 Code::ExtraICState extra_ic_state) |
| 704 : stub_compiler_(stub_compiler), | 641 : stub_compiler_(stub_compiler), |
| 705 arguments_(arguments), | 642 arguments_(arguments), |
| 706 name_(name), | 643 name_(name), |
| 707 extra_ic_state_(extra_ic_state) {} | 644 extra_ic_state_(extra_ic_state) {} |
| 708 | 645 |
| 709 MaybeObject* Compile(MacroAssembler* masm, | 646 void Compile(MacroAssembler* masm, |
| 710 JSObject* object, | 647 Handle<JSObject> object, |
| 711 JSObject* holder, | 648 Handle<JSObject> holder, |
| 712 String* name, | 649 Handle<String> name, |
| 713 LookupResult* lookup, | 650 LookupResult* lookup, |
| 714 Register receiver, | 651 Register receiver, |
| 715 Register scratch1, | 652 Register scratch1, |
| 716 Register scratch2, | 653 Register scratch2, |
| 717 Register scratch3, | 654 Register scratch3, |
| 718 Label* miss) { | 655 Label* miss) { |
| 719 ASSERT(holder->HasNamedInterceptor()); | 656 ASSERT(holder->HasNamedInterceptor()); |
| 720 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 657 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 721 | 658 |
| 722 // Check that the receiver isn't a smi. | 659 // Check that the receiver isn't a smi. |
| 723 __ JumpIfSmi(receiver, miss); | 660 __ JumpIfSmi(receiver, miss); |
| 724 | |
| 725 CallOptimization optimization(lookup); | 661 CallOptimization optimization(lookup); |
| 726 | |
| 727 if (optimization.is_constant_call()) { | 662 if (optimization.is_constant_call()) { |
| 728 return CompileCacheable(masm, | 663 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, |
| 729 object, | 664 holder, lookup, name, optimization, miss); |
| 730 receiver, | |
| 731 scratch1, | |
| 732 scratch2, | |
| 733 scratch3, | |
| 734 holder, | |
| 735 lookup, | |
| 736 name, | |
| 737 optimization, | |
| 738 miss); | |
| 739 } else { | 665 } else { |
| 740 CompileRegular(masm, | 666 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, |
| 741 object, | 667 name, holder, miss); |
| 742 receiver, | |
| 743 scratch1, | |
| 744 scratch2, | |
| 745 scratch3, | |
| 746 name, | |
| 747 holder, | |
| 748 miss); | |
| 749 return masm->isolate()->heap()->undefined_value(); | |
| 750 } | 668 } |
| 751 } | 669 } |
| 752 | 670 |
| 753 private: | 671 private: |
| 754 MaybeObject* CompileCacheable(MacroAssembler* masm, | 672 void CompileCacheable(MacroAssembler* masm, |
| 755 JSObject* object, | 673 Handle<JSObject> object, |
| 756 Register receiver, | 674 Register receiver, |
| 757 Register scratch1, | 675 Register scratch1, |
| 758 Register scratch2, | 676 Register scratch2, |
| 759 Register scratch3, | 677 Register scratch3, |
| 760 JSObject* interceptor_holder, | 678 Handle<JSObject> interceptor_holder, |
| 761 LookupResult* lookup, | 679 LookupResult* lookup, |
| 762 String* name, | 680 Handle<String> name, |
| 763 const CallOptimization& optimization, | 681 const CallOptimization& optimization, |
| 764 Label* miss_label) { | 682 Label* miss_label) { |
| 765 ASSERT(optimization.is_constant_call()); | 683 ASSERT(optimization.is_constant_call()); |
| 766 ASSERT(!lookup->holder()->IsGlobalObject()); | 684 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 767 | |
| 768 Counters* counters = masm->isolate()->counters(); | 685 Counters* counters = masm->isolate()->counters(); |
| 769 | |
| 770 int depth1 = kInvalidProtoDepth; | 686 int depth1 = kInvalidProtoDepth; |
| 771 int depth2 = kInvalidProtoDepth; | 687 int depth2 = kInvalidProtoDepth; |
| 772 bool can_do_fast_api_call = false; | 688 bool can_do_fast_api_call = false; |
| 773 if (optimization.is_simple_api_call() && | 689 if (optimization.is_simple_api_call() && |
| 774 !lookup->holder()->IsGlobalObject()) { | 690 !lookup->holder()->IsGlobalObject()) { |
| 775 depth1 = | 691 depth1 = optimization.GetPrototypeDepthOfExpectedType( |
| 776 optimization.GetPrototypeDepthOfExpectedType(object, | 692 object, interceptor_holder); |
| 777 interceptor_holder); | |
| 778 if (depth1 == kInvalidProtoDepth) { | 693 if (depth1 == kInvalidProtoDepth) { |
| 779 depth2 = | 694 depth2 = optimization.GetPrototypeDepthOfExpectedType( |
| 780 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 695 interceptor_holder, Handle<JSObject>(lookup->holder())); |
| 781 lookup->holder()); | |
| 782 } | 696 } |
| 783 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | 697 can_do_fast_api_call = |
| 784 (depth2 != kInvalidProtoDepth); | 698 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; |
| 785 } | 699 } |
| 786 | 700 |
| 787 __ IncrementCounter(counters->call_const_interceptor(), 1, | 701 __ IncrementCounter(counters->call_const_interceptor(), 1, |
| 788 scratch1, scratch2); | 702 scratch1, scratch2); |
| 789 | 703 |
| 790 if (can_do_fast_api_call) { | 704 if (can_do_fast_api_call) { |
| 791 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, | 705 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, |
| 792 scratch1, scratch2); | 706 scratch1, scratch2); |
| 793 ReserveSpaceForFastApiCall(masm, scratch1); | 707 ReserveSpaceForFastApiCall(masm, scratch1); |
| 794 } | 708 } |
| 795 | 709 |
| 796 // Check that the maps from receiver to interceptor's holder | 710 // Check that the maps from receiver to interceptor's holder |
| 797 // haven't changed and thus we can invoke interceptor. | 711 // haven't changed and thus we can invoke interceptor. |
| 798 Label miss_cleanup; | 712 Label miss_cleanup; |
| 799 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 713 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 800 Register holder = | 714 Register holder = |
| 801 stub_compiler_->CheckPrototypes(object, receiver, | 715 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 802 interceptor_holder, scratch1, | 716 scratch1, scratch2, scratch3, |
| 803 scratch2, scratch3, name, depth1, miss); | 717 name, depth1, miss); |
| 804 | 718 |
| 805 // Invoke an interceptor and if it provides a value, | 719 // Invoke an interceptor and if it provides a value, |
| 806 // branch to |regular_invoke|. | 720 // branch to |regular_invoke|. |
| 807 Label regular_invoke; | 721 Label regular_invoke; |
| 808 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, | 722 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, |
| 809 ®ular_invoke); | 723 ®ular_invoke); |
| 810 | 724 |
| 811 // Interceptor returned nothing for this property. Try to use cached | 725 // Interceptor returned nothing for this property. Try to use cached |
| 812 // constant function. | 726 // constant function. |
| 813 | 727 |
| 814 // Check that the maps from interceptor's holder to constant function's | 728 // Check that the maps from interceptor's holder to constant function's |
| 815 // holder haven't changed and thus we can use cached constant function. | 729 // holder haven't changed and thus we can use cached constant function. |
| 816 if (interceptor_holder != lookup->holder()) { | 730 if (*interceptor_holder != lookup->holder()) { |
| 817 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 731 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
| 818 lookup->holder(), scratch1, | 732 Handle<JSObject>(lookup->holder()), |
| 819 scratch2, scratch3, name, depth2, miss); | 733 scratch1, scratch2, scratch3, |
| 734 name, depth2, miss); |
| 820 } else { | 735 } else { |
| 821 // CheckPrototypes has a side effect of fetching a 'holder' | 736 // CheckPrototypes has a side effect of fetching a 'holder' |
| 822 // for API (object which is instanceof for the signature). It's | 737 // for API (object which is instanceof for the signature). It's |
| 823 // safe to omit it here, as if present, it should be fetched | 738 // safe to omit it here, as if present, it should be fetched |
| 824 // by the previous CheckPrototypes. | 739 // by the previous CheckPrototypes. |
| 825 ASSERT(depth2 == kInvalidProtoDepth); | 740 ASSERT(depth2 == kInvalidProtoDepth); |
| 826 } | 741 } |
| 827 | 742 |
| 828 // Invoke function. | 743 // Invoke function. |
| 829 if (can_do_fast_api_call) { | 744 if (can_do_fast_api_call) { |
| 830 MaybeObject* result = GenerateFastApiDirectCall(masm, | 745 GenerateFastApiDirectCall(masm, optimization, arguments_.immediate()); |
| 831 optimization, | |
| 832 arguments_.immediate()); | |
| 833 if (result->IsFailure()) return result; | |
| 834 } else { | 746 } else { |
| 835 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | 747 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 836 ? CALL_AS_FUNCTION | 748 ? CALL_AS_FUNCTION |
| 837 : CALL_AS_METHOD; | 749 : CALL_AS_METHOD; |
| 838 __ InvokeFunction(optimization.constant_function(), arguments_, | 750 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 839 JUMP_FUNCTION, call_kind); | 751 JUMP_FUNCTION, call_kind); |
| 840 } | 752 } |
| 841 | 753 |
| 842 // Deferred code for fast API call case---clean preallocated space. | 754 // Deferred code for fast API call case---clean preallocated space. |
| 843 if (can_do_fast_api_call) { | 755 if (can_do_fast_api_call) { |
| 844 __ bind(&miss_cleanup); | 756 __ bind(&miss_cleanup); |
| 845 FreeSpaceForFastApiCall(masm); | 757 FreeSpaceForFastApiCall(masm); |
| 846 __ Branch(miss_label); | 758 __ Branch(miss_label); |
| 847 } | 759 } |
| 848 | 760 |
| 849 // Invoke a regular function. | 761 // Invoke a regular function. |
| 850 __ bind(®ular_invoke); | 762 __ bind(®ular_invoke); |
| 851 if (can_do_fast_api_call) { | 763 if (can_do_fast_api_call) { |
| 852 FreeSpaceForFastApiCall(masm); | 764 FreeSpaceForFastApiCall(masm); |
| 853 } | 765 } |
| 854 | |
| 855 return masm->isolate()->heap()->undefined_value(); | |
| 856 } | 766 } |
| 857 | 767 |
| 858 void CompileRegular(MacroAssembler* masm, | 768 void CompileRegular(MacroAssembler* masm, |
| 859 JSObject* object, | 769 Handle<JSObject> object, |
| 860 Register receiver, | 770 Register receiver, |
| 861 Register scratch1, | 771 Register scratch1, |
| 862 Register scratch2, | 772 Register scratch2, |
| 863 Register scratch3, | 773 Register scratch3, |
| 864 String* name, | 774 Handle<String> name, |
| 865 JSObject* interceptor_holder, | 775 Handle<JSObject> interceptor_holder, |
| 866 Label* miss_label) { | 776 Label* miss_label) { |
| 867 Register holder = | 777 Register holder = |
| 868 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 778 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
| 869 scratch1, scratch2, scratch3, name, | 779 scratch1, scratch2, scratch3, |
| 870 miss_label); | 780 name, miss_label); |
| 871 | 781 |
| 872 // Call a runtime function to load the interceptor property. | 782 // Call a runtime function to load the interceptor property. |
| 873 FrameScope scope(masm, StackFrame::INTERNAL); | 783 FrameScope scope(masm, StackFrame::INTERNAL); |
| 874 // Save the name_ register across the call. | 784 // Save the name_ register across the call. |
| 875 __ push(name_); | 785 __ push(name_); |
| 876 | 786 |
| 877 PushInterceptorArguments(masm, | 787 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 878 receiver, | |
| 879 holder, | |
| 880 name_, | |
| 881 interceptor_holder); | |
| 882 | 788 |
| 883 __ CallExternalReference( | 789 __ CallExternalReference( |
| 884 ExternalReference( | 790 ExternalReference( |
| 885 IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 791 IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 886 masm->isolate()), | 792 masm->isolate()), |
| 887 5); | 793 5); |
| 888 | |
| 889 // Restore the name_ register. | 794 // Restore the name_ register. |
| 890 __ pop(name_); | 795 __ pop(name_); |
| 891 | |
| 892 // Leave the internal frame. | 796 // Leave the internal frame. |
| 893 } | 797 } |
| 894 | 798 |
| 895 void LoadWithInterceptor(MacroAssembler* masm, | 799 void LoadWithInterceptor(MacroAssembler* masm, |
| 896 Register receiver, | 800 Register receiver, |
| 897 Register holder, | 801 Register holder, |
| 898 JSObject* holder_obj, | 802 Handle<JSObject> holder_obj, |
| 899 Register scratch, | 803 Register scratch, |
| 900 Label* interceptor_succeeded) { | 804 Label* interceptor_succeeded) { |
| 901 { | 805 { |
| 902 FrameScope scope(masm, StackFrame::INTERNAL); | 806 FrameScope scope(masm, StackFrame::INTERNAL); |
| 903 | 807 |
| 904 __ Push(holder, name_); | 808 __ Push(holder, name_); |
| 905 | |
| 906 CompileCallLoadPropertyWithInterceptor(masm, | 809 CompileCallLoadPropertyWithInterceptor(masm, |
| 907 receiver, | 810 receiver, |
| 908 holder, | 811 holder, |
| 909 name_, | 812 name_, |
| 910 holder_obj); | 813 holder_obj); |
| 911 | |
| 912 __ pop(name_); // Restore the name. | 814 __ pop(name_); // Restore the name. |
| 913 __ pop(receiver); // Restore the holder. | 815 __ pop(receiver); // Restore the holder. |
| 914 } | 816 } |
| 915 | |
| 916 // If interceptor returns no-result sentinel, call the constant function. | 817 // If interceptor returns no-result sentinel, call the constant function. |
| 917 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 818 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 918 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); | 819 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); |
| 919 } | 820 } |
| 920 | 821 |
| 921 StubCompiler* stub_compiler_; | 822 StubCompiler* stub_compiler_; |
| 922 const ParameterCount& arguments_; | 823 const ParameterCount& arguments_; |
| 923 Register name_; | 824 Register name_; |
| 924 Code::ExtraICState extra_ic_state_; | 825 Code::ExtraICState extra_ic_state_; |
| 925 }; | 826 }; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 938 GlobalObject::EnsurePropertyCell(global, name); | 839 GlobalObject::EnsurePropertyCell(global, name); |
| 939 ASSERT(cell->value()->IsTheHole()); | 840 ASSERT(cell->value()->IsTheHole()); |
| 940 __ li(scratch, Operand(cell)); | 841 __ li(scratch, Operand(cell)); |
| 941 __ lw(scratch, | 842 __ lw(scratch, |
| 942 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 843 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
| 943 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 844 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 944 __ Branch(miss, ne, scratch, Operand(at)); | 845 __ Branch(miss, ne, scratch, Operand(at)); |
| 945 } | 846 } |
| 946 | 847 |
| 947 | 848 |
| 948 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 949 // handlified. | |
| 950 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( | |
| 951 MacroAssembler* masm, | |
| 952 GlobalObject* global, | |
| 953 String* name, | |
| 954 Register scratch, | |
| 955 Label* miss) { | |
| 956 Object* probe; | |
| 957 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | |
| 958 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | |
| 959 } | |
| 960 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | |
| 961 ASSERT(cell->value()->IsTheHole()); | |
| 962 __ li(scratch, Operand(Handle<Object>(cell))); | |
| 963 __ lw(scratch, | |
| 964 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | |
| 965 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | |
| 966 __ Branch(miss, ne, scratch, Operand(at)); | |
| 967 return cell; | |
| 968 } | |
| 969 | |
| 970 | |
| 971 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 849 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
| 972 // from object to (but not including) holder. | 850 // from object to (but not including) holder. |
| 973 static void GenerateCheckPropertyCells(MacroAssembler* masm, | 851 static void GenerateCheckPropertyCells(MacroAssembler* masm, |
| 974 Handle<JSObject> object, | 852 Handle<JSObject> object, |
| 975 Handle<JSObject> holder, | 853 Handle<JSObject> holder, |
| 976 Handle<String> name, | 854 Handle<String> name, |
| 977 Register scratch, | 855 Register scratch, |
| 978 Label* miss) { | 856 Label* miss) { |
| 979 Handle<JSObject> current = object; | 857 Handle<JSObject> current = object; |
| 980 while (!current.is_identical_to(holder)) { | 858 while (!current.is_identical_to(holder)) { |
| 981 if (current->IsGlobalObject()) { | 859 if (current->IsGlobalObject()) { |
| 982 GenerateCheckPropertyCell(masm, | 860 GenerateCheckPropertyCell(masm, |
| 983 Handle<GlobalObject>::cast(current), | 861 Handle<GlobalObject>::cast(current), |
| 984 name, | 862 name, |
| 985 scratch, | 863 scratch, |
| 986 miss); | 864 miss); |
| 987 } | 865 } |
| 988 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 866 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
| 989 } | 867 } |
| 990 } | 868 } |
| 991 | 869 |
| 992 | 870 |
| 993 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 994 // handlified. | |
| 995 MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( | |
| 996 MacroAssembler* masm, | |
| 997 JSObject* object, | |
| 998 JSObject* holder, | |
| 999 String* name, | |
| 1000 Register scratch, | |
| 1001 Label* miss) { | |
| 1002 JSObject* current = object; | |
| 1003 while (current != holder) { | |
| 1004 if (current->IsGlobalObject()) { | |
| 1005 // Returns a cell or a failure. | |
| 1006 MaybeObject* result = TryGenerateCheckPropertyCell( | |
| 1007 masm, | |
| 1008 GlobalObject::cast(current), | |
| 1009 name, | |
| 1010 scratch, | |
| 1011 miss); | |
| 1012 if (result->IsFailure()) return result; | |
| 1013 } | |
| 1014 ASSERT(current->IsJSObject()); | |
| 1015 current = JSObject::cast(current->GetPrototype()); | |
| 1016 } | |
| 1017 return NULL; | |
| 1018 } | |
| 1019 | |
| 1020 | |
| 1021 // Convert and store int passed in register ival to IEEE 754 single precision | 871 // Convert and store int passed in register ival to IEEE 754 single precision |
| 1022 // floating point value at memory location (dst + 4 * wordoffset) | 872 // floating point value at memory location (dst + 4 * wordoffset) |
| 1023 // If FPU is available use it for conversion. | 873 // If FPU is available use it for conversion. |
| 1024 static void StoreIntAsFloat(MacroAssembler* masm, | 874 static void StoreIntAsFloat(MacroAssembler* masm, |
| 1025 Register dst, | 875 Register dst, |
| 1026 Register wordoffset, | 876 Register wordoffset, |
| 1027 Register ival, | 877 Register ival, |
| 1028 Register fval, | 878 Register fval, |
| 1029 Register scratch1, | 879 Register scratch1, |
| 1030 Register scratch2) { | 880 Register scratch2) { |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1233 // If we've skipped any global objects, it's not enough to verify that | 1083 // If we've skipped any global objects, it's not enough to verify that |
| 1234 // their maps haven't changed. We also need to check that the property | 1084 // their maps haven't changed. We also need to check that the property |
| 1235 // cell for the property is still empty. | 1085 // cell for the property is still empty. |
| 1236 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1086 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1237 | 1087 |
| 1238 // Return the register containing the holder. | 1088 // Return the register containing the holder. |
| 1239 return reg; | 1089 return reg; |
| 1240 } | 1090 } |
| 1241 | 1091 |
| 1242 | 1092 |
| 1243 Register StubCompiler::CheckPrototypes(JSObject* object, | |
| 1244 Register object_reg, | |
| 1245 JSObject* holder, | |
| 1246 Register holder_reg, | |
| 1247 Register scratch1, | |
| 1248 Register scratch2, | |
| 1249 String* name, | |
| 1250 int save_at_depth, | |
| 1251 Label* miss) { | |
| 1252 // Make sure there's no overlap between holder and object registers. | |
| 1253 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | |
| 1254 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | |
| 1255 && !scratch2.is(scratch1)); | |
| 1256 | |
| 1257 // Keep track of the current object in register reg. | |
| 1258 Register reg = object_reg; | |
| 1259 int depth = 0; | |
| 1260 | |
| 1261 if (save_at_depth == depth) { | |
| 1262 __ sw(reg, MemOperand(sp)); | |
| 1263 } | |
| 1264 | |
| 1265 // Check the maps in the prototype chain. | |
| 1266 // Traverse the prototype chain from the object and do map checks. | |
| 1267 JSObject* current = object; | |
| 1268 while (current != holder) { | |
| 1269 depth++; | |
| 1270 | |
| 1271 // Only global objects and objects that do not require access | |
| 1272 // checks are allowed in stubs. | |
| 1273 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | |
| 1274 | |
| 1275 ASSERT(current->GetPrototype()->IsJSObject()); | |
| 1276 JSObject* prototype = JSObject::cast(current->GetPrototype()); | |
| 1277 if (!current->HasFastProperties() && | |
| 1278 !current->IsJSGlobalObject() && | |
| 1279 !current->IsJSGlobalProxy()) { | |
| 1280 if (!name->IsSymbol()) { | |
| 1281 MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name); | |
| 1282 Object* lookup_result = NULL; // Initialization to please compiler. | |
| 1283 if (!maybe_lookup_result->ToObject(&lookup_result)) { | |
| 1284 set_failure(Failure::cast(maybe_lookup_result)); | |
| 1285 return reg; | |
| 1286 } | |
| 1287 name = String::cast(lookup_result); | |
| 1288 } | |
| 1289 ASSERT(current->property_dictionary()->FindEntry(name) == | |
| 1290 StringDictionary::kNotFound); | |
| 1291 | |
| 1292 MaybeObject* negative_lookup = | |
| 1293 TryGenerateDictionaryNegativeLookup(masm(), | |
| 1294 miss, | |
| 1295 reg, | |
| 1296 name, | |
| 1297 scratch1, | |
| 1298 scratch2); | |
| 1299 | |
| 1300 if (negative_lookup->IsFailure()) { | |
| 1301 set_failure(Failure::cast(negative_lookup)); | |
| 1302 return reg; | |
| 1303 } | |
| 1304 | |
| 1305 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1306 reg = holder_reg; // From now the object is in holder_reg. | |
| 1307 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
| 1308 } else if (heap()->InNewSpace(prototype)) { | |
| 1309 // Get the map of the current object. | |
| 1310 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1311 | |
| 1312 // Branch on the result of the map check. | |
| 1313 __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); | |
| 1314 | |
| 1315 // Check access rights to the global object. This has to happen | |
| 1316 // after the map check so that we know that the object is | |
| 1317 // actually a global object. | |
| 1318 if (current->IsJSGlobalProxy()) { | |
| 1319 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1320 // Restore scratch register to be the map of the object. In the | |
| 1321 // new space case below, we load the prototype from the map in | |
| 1322 // the scratch register. | |
| 1323 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1324 } | |
| 1325 | |
| 1326 reg = holder_reg; // From now the object is in holder_reg. | |
| 1327 // The prototype is in new space; we cannot store a reference | |
| 1328 // to it in the code. Load it from the map. | |
| 1329 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); | |
| 1330 } else { | |
| 1331 // Check the map of the current object. | |
| 1332 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1333 // Branch on the result of the map check. | |
| 1334 __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); | |
| 1335 // Check access rights to the global object. This has to happen | |
| 1336 // after the map check so that we know that the object is | |
| 1337 // actually a global object. | |
| 1338 if (current->IsJSGlobalProxy()) { | |
| 1339 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1340 } | |
| 1341 // The prototype is in old space; load it directly. | |
| 1342 reg = holder_reg; // From now the object is in holder_reg. | |
| 1343 __ li(reg, Operand(Handle<JSObject>(prototype))); | |
| 1344 } | |
| 1345 | |
| 1346 if (save_at_depth == depth) { | |
| 1347 __ sw(reg, MemOperand(sp)); | |
| 1348 } | |
| 1349 | |
| 1350 // Go to the next object in the prototype chain. | |
| 1351 current = prototype; | |
| 1352 } | |
| 1353 | |
| 1354 // Check the holder map. | |
| 1355 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); | |
| 1356 __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map()))); | |
| 1357 | |
| 1358 // Log the check depth. | |
| 1359 LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); | |
| 1360 // Perform security check for access to the global object. | |
| 1361 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | |
| 1362 if (holder->IsJSGlobalProxy()) { | |
| 1363 __ CheckAccessGlobalProxy(reg, scratch1, miss); | |
| 1364 } | |
| 1365 | |
| 1366 // If we've skipped any global objects, it's not enough to verify | |
| 1367 // that their maps haven't changed. We also need to check that the | |
| 1368 // property cell for the property is still empty. | |
| 1369 | |
| 1370 MaybeObject* result = TryGenerateCheckPropertyCells(masm(), | |
| 1371 object, | |
| 1372 holder, | |
| 1373 name, | |
| 1374 scratch1, | |
| 1375 miss); | |
| 1376 if (result->IsFailure()) set_failure(Failure::cast(result)); | |
| 1377 | |
| 1378 // Return the register containing the holder. | |
| 1379 return reg; | |
| 1380 } | |
| 1381 | |
| 1382 | |
| 1383 void StubCompiler::GenerateLoadField(Handle<JSObject> object, | 1093 void StubCompiler::GenerateLoadField(Handle<JSObject> object, |
| 1384 Handle<JSObject> holder, | 1094 Handle<JSObject> holder, |
| 1385 Register receiver, | 1095 Register receiver, |
| 1386 Register scratch1, | 1096 Register scratch1, |
| 1387 Register scratch2, | 1097 Register scratch2, |
| 1388 Register scratch3, | 1098 Register scratch3, |
| 1389 int index, | 1099 int index, |
| 1390 Handle<String> name, | 1100 Handle<String> name, |
| 1391 Label* miss) { | 1101 Label* miss) { |
| 1392 // Check that the receiver isn't a smi. | 1102 // Check that the receiver isn't a smi. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1417 Register reg = | 1127 Register reg = |
| 1418 CheckPrototypes(object, receiver, holder, | 1128 CheckPrototypes(object, receiver, holder, |
| 1419 scratch1, scratch2, scratch3, name, miss); | 1129 scratch1, scratch2, scratch3, name, miss); |
| 1420 | 1130 |
| 1421 // Return the constant value. | 1131 // Return the constant value. |
| 1422 __ li(v0, Operand(value)); | 1132 __ li(v0, Operand(value)); |
| 1423 __ Ret(); | 1133 __ Ret(); |
| 1424 } | 1134 } |
| 1425 | 1135 |
| 1426 | 1136 |
| 1427 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, | 1137 void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, |
| 1428 JSObject* holder, | 1138 Handle<JSObject> holder, |
| 1429 Register receiver, | 1139 Register receiver, |
| 1430 Register name_reg, | 1140 Register name_reg, |
| 1431 Register scratch1, | 1141 Register scratch1, |
| 1432 Register scratch2, | 1142 Register scratch2, |
| 1433 Register scratch3, | 1143 Register scratch3, |
| 1434 AccessorInfo* callback, | 1144 Handle<AccessorInfo> callback, |
| 1435 String* name, | 1145 Handle<String> name, |
| 1436 Label* miss) { | 1146 Label* miss) { |
| 1437 // Check that the receiver isn't a smi. | 1147 // Check that the receiver isn't a smi. |
| 1438 __ JumpIfSmi(receiver, miss, scratch1); | 1148 __ JumpIfSmi(receiver, miss, scratch1); |
| 1439 | 1149 |
| 1440 // Check that the maps haven't changed. | 1150 // Check that the maps haven't changed. |
| 1441 Register reg = | 1151 Register reg = CheckPrototypes(object, receiver, holder, scratch1, |
| 1442 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, | 1152 scratch2, scratch3, name, miss); |
| 1443 name, miss); | |
| 1444 | 1153 |
| 1445 // Build AccessorInfo::args_ list on the stack and push property name below | 1154 // Build AccessorInfo::args_ list on the stack and push property name below |
| 1446 // the exit frame to make GC aware of them and store pointers to them. | 1155 // the exit frame to make GC aware of them and store pointers to them. |
| 1447 __ push(receiver); | 1156 __ push(receiver); |
| 1448 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ | 1157 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ |
| 1449 Handle<AccessorInfo> callback_handle(callback); | 1158 if (heap()->InNewSpace(callback->data())) { |
| 1450 if (heap()->InNewSpace(callback_handle->data())) { | 1159 __ li(scratch3, callback); |
| 1451 __ li(scratch3, callback_handle); | |
| 1452 __ lw(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); | 1160 __ lw(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); |
| 1453 } else { | 1161 } else { |
| 1454 __ li(scratch3, Handle<Object>(callback_handle->data())); | 1162 __ li(scratch3, Handle<Object>(callback->data())); |
| 1455 } | 1163 } |
| 1456 __ Push(reg, scratch3, name_reg); | 1164 __ Push(reg, scratch3, name_reg); |
| 1457 __ mov(a2, scratch2); // Saved in case scratch2 == a1. | 1165 __ mov(a2, scratch2); // Saved in case scratch2 == a1. |
| 1458 __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String> | 1166 __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String> |
| 1459 | 1167 |
| 1460 Address getter_address = v8::ToCData<Address>(callback->getter()); | |
| 1461 ApiFunction fun(getter_address); | |
| 1462 | |
| 1463 // NOTE: the O32 abi requires a0 to hold a special pointer when returning a | 1168 // NOTE: the O32 abi requires a0 to hold a special pointer when returning a |
| 1464 // struct from the function (which is currently the case). This means we pass | 1169 // struct from the function (which is currently the case). This means we pass |
| 1465 // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn | 1170 // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn |
| 1466 // will handle setting up a0. | 1171 // will handle setting up a0. |
| 1467 | 1172 |
| 1468 const int kApiStackSpace = 1; | 1173 const int kApiStackSpace = 1; |
| 1469 | |
| 1470 FrameScope frame_scope(masm(), StackFrame::MANUAL); | 1174 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
| 1471 __ EnterExitFrame(false, kApiStackSpace); | 1175 __ EnterExitFrame(false, kApiStackSpace); |
| 1472 | 1176 |
| 1473 // Create AccessorInfo instance on the stack above the exit frame with | 1177 // Create AccessorInfo instance on the stack above the exit frame with |
| 1474 // scratch2 (internal::Object **args_) as the data. | 1178 // scratch2 (internal::Object **args_) as the data. |
| 1475 __ sw(a2, MemOperand(sp, kPointerSize)); | 1179 __ sw(a2, MemOperand(sp, kPointerSize)); |
| 1476 // a2 (second argument - see note above) = AccessorInfo& | 1180 // a2 (second argument - see note above) = AccessorInfo& |
| 1477 __ Addu(a2, sp, kPointerSize); | 1181 __ Addu(a2, sp, kPointerSize); |
| 1478 | 1182 |
| 1479 // Emitting a stub call may try to allocate (if the code is not | 1183 const int kStackUnwindSpace = 4; |
| 1480 // already generated). Do not allow the assembler to perform a | 1184 Address getter_address = v8::ToCData<Address>(callback->getter()); |
| 1481 // garbage collection but instead return the allocation failure | 1185 ApiFunction fun(getter_address); |
| 1482 // object. | |
| 1483 ExternalReference ref = | 1186 ExternalReference ref = |
| 1484 ExternalReference(&fun, | 1187 ExternalReference(&fun, |
| 1485 ExternalReference::DIRECT_GETTER_CALL, | 1188 ExternalReference::DIRECT_GETTER_CALL, |
| 1486 masm()->isolate()); | 1189 masm()->isolate()); |
| 1487 // 4 args - will be freed later by LeaveExitFrame. | 1190 __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 1488 return masm()->TryCallApiFunctionAndReturn(ref, 4); | |
| 1489 } | 1191 } |
| 1490 | 1192 |
| 1491 | 1193 |
| 1492 void StubCompiler::GenerateLoadInterceptor(JSObject* object, | 1194 void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, |
| 1493 JSObject* interceptor_holder, | 1195 Handle<JSObject> interceptor_holder, |
| 1494 LookupResult* lookup, | 1196 LookupResult* lookup, |
| 1495 Register receiver, | 1197 Register receiver, |
| 1496 Register name_reg, | 1198 Register name_reg, |
| 1497 Register scratch1, | 1199 Register scratch1, |
| 1498 Register scratch2, | 1200 Register scratch2, |
| 1499 Register scratch3, | 1201 Register scratch3, |
| 1500 String* name, | 1202 Handle<String> name, |
| 1501 Label* miss) { | 1203 Label* miss) { |
| 1502 ASSERT(interceptor_holder->HasNamedInterceptor()); | 1204 ASSERT(interceptor_holder->HasNamedInterceptor()); |
| 1503 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1205 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1504 | 1206 |
| 1505 // Check that the receiver isn't a smi. | 1207 // Check that the receiver isn't a smi. |
| 1506 __ JumpIfSmi(receiver, miss); | 1208 __ JumpIfSmi(receiver, miss); |
| 1507 | 1209 |
| 1508 // So far the most popular follow ups for interceptor loads are FIELD | 1210 // So far the most popular follow ups for interceptor loads are FIELD |
| 1509 // and CALLBACKS, so inline only them, other cases may be added | 1211 // and CALLBACKS, so inline only them, other cases may be added |
| 1510 // later. | 1212 // later. |
| 1511 bool compile_followup_inline = false; | 1213 bool compile_followup_inline = false; |
| 1512 if (lookup->IsProperty() && lookup->IsCacheable()) { | 1214 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 1513 if (lookup->type() == FIELD) { | 1215 if (lookup->type() == FIELD) { |
| 1514 compile_followup_inline = true; | 1216 compile_followup_inline = true; |
| 1515 } else if (lookup->type() == CALLBACKS && | 1217 } else if (lookup->type() == CALLBACKS && |
| 1516 lookup->GetCallbackObject()->IsAccessorInfo() && | 1218 lookup->GetCallbackObject()->IsAccessorInfo()) { |
| 1517 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) { | 1219 compile_followup_inline = |
| 1518 compile_followup_inline = true; | 1220 AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; |
| 1519 } | 1221 } |
| 1520 } | 1222 } |
| 1521 | 1223 |
| 1522 if (compile_followup_inline) { | 1224 if (compile_followup_inline) { |
| 1523 // Compile the interceptor call, followed by inline code to load the | 1225 // Compile the interceptor call, followed by inline code to load the |
| 1524 // property from further up the prototype chain if the call fails. | 1226 // property from further up the prototype chain if the call fails. |
| 1525 // Check that the maps haven't changed. | 1227 // Check that the maps haven't changed. |
| 1526 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1228 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
| 1527 scratch1, scratch2, scratch3, | 1229 scratch1, scratch2, scratch3, |
| 1528 name, miss); | 1230 name, miss); |
| 1529 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1231 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
| 1530 | 1232 |
| 1531 // Save necessary data before invoking an interceptor. | 1233 // Save necessary data before invoking an interceptor. |
| 1532 // Requires a frame to make GC aware of pushed pointers. | 1234 // Requires a frame to make GC aware of pushed pointers. |
| 1533 { | 1235 { |
| 1534 FrameScope frame_scope(masm(), StackFrame::INTERNAL); | 1236 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
| 1535 | |
| 1536 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1237 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1537 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1238 // CALLBACKS case needs a receiver to be passed into C++ callback. |
| 1538 __ Push(receiver, holder_reg, name_reg); | 1239 __ Push(receiver, holder_reg, name_reg); |
| 1539 } else { | 1240 } else { |
| 1540 __ Push(holder_reg, name_reg); | 1241 __ Push(holder_reg, name_reg); |
| 1541 } | 1242 } |
| 1542 | |
| 1543 // Invoke an interceptor. Note: map checks from receiver to | 1243 // Invoke an interceptor. Note: map checks from receiver to |
| 1544 // interceptor's holder has been compiled before (see a caller | 1244 // interceptor's holder has been compiled before (see a caller |
| 1545 // of this method). | 1245 // of this method). |
| 1546 CompileCallLoadPropertyWithInterceptor(masm(), | 1246 CompileCallLoadPropertyWithInterceptor(masm(), |
| 1547 receiver, | 1247 receiver, |
| 1548 holder_reg, | 1248 holder_reg, |
| 1549 name_reg, | 1249 name_reg, |
| 1550 interceptor_holder); | 1250 interceptor_holder); |
| 1551 | |
| 1552 // Check if interceptor provided a value for property. If it's | 1251 // Check if interceptor provided a value for property. If it's |
| 1553 // the case, return immediately. | 1252 // the case, return immediately. |
| 1554 Label interceptor_failed; | 1253 Label interceptor_failed; |
| 1555 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); | 1254 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1556 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1)); | 1255 __ Branch(&interceptor_failed, eq, v0, Operand(scratch1)); |
| 1557 frame_scope.GenerateLeaveFrame(); | 1256 frame_scope.GenerateLeaveFrame(); |
| 1558 __ Ret(); | 1257 __ Ret(); |
| 1559 | 1258 |
| 1560 __ bind(&interceptor_failed); | 1259 __ bind(&interceptor_failed); |
| 1561 __ pop(name_reg); | 1260 __ pop(name_reg); |
| 1562 __ pop(holder_reg); | 1261 __ pop(holder_reg); |
| 1563 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1262 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1564 __ pop(receiver); | 1263 __ pop(receiver); |
| 1565 } | 1264 } |
| 1566 | |
| 1567 // Leave the internal frame. | 1265 // Leave the internal frame. |
| 1568 } | 1266 } |
| 1569 | |
| 1570 // Check that the maps from interceptor's holder to lookup's holder | 1267 // Check that the maps from interceptor's holder to lookup's holder |
| 1571 // haven't changed. And load lookup's holder into |holder| register. | 1268 // haven't changed. And load lookup's holder into |holder| register. |
| 1572 if (interceptor_holder != lookup->holder()) { | 1269 if (*interceptor_holder != lookup->holder()) { |
| 1573 holder_reg = CheckPrototypes(interceptor_holder, | 1270 holder_reg = CheckPrototypes(interceptor_holder, |
| 1574 holder_reg, | 1271 holder_reg, |
| 1575 lookup->holder(), | 1272 Handle<JSObject>(lookup->holder()), |
| 1576 scratch1, | 1273 scratch1, |
| 1577 scratch2, | 1274 scratch2, |
| 1578 scratch3, | 1275 scratch3, |
| 1579 name, | 1276 name, |
| 1580 miss); | 1277 miss); |
| 1581 } | 1278 } |
| 1582 | 1279 |
| 1583 if (lookup->type() == FIELD) { | 1280 if (lookup->type() == FIELD) { |
| 1584 // We found FIELD property in prototype chain of interceptor's holder. | 1281 // We found FIELD property in prototype chain of interceptor's holder. |
| 1585 // Retrieve a field from field's holder. | 1282 // Retrieve a field from field's holder. |
| 1586 GenerateFastPropertyLoad(masm(), v0, holder_reg, | 1283 GenerateFastPropertyLoad(masm(), v0, holder_reg, |
| 1587 Handle<JSObject>(lookup->holder()), | 1284 Handle<JSObject>(lookup->holder()), |
| 1588 lookup->GetFieldIndex()); | 1285 lookup->GetFieldIndex()); |
| 1589 __ Ret(); | 1286 __ Ret(); |
| 1590 } else { | 1287 } else { |
| 1591 // We found CALLBACKS property in prototype chain of interceptor's | 1288 // We found CALLBACKS property in prototype chain of interceptor's |
| 1592 // holder. | 1289 // holder. |
| 1593 ASSERT(lookup->type() == CALLBACKS); | 1290 ASSERT(lookup->type() == CALLBACKS); |
| 1594 ASSERT(lookup->GetCallbackObject()->IsAccessorInfo()); | 1291 Handle<AccessorInfo> callback( |
| 1595 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); | 1292 AccessorInfo::cast(lookup->GetCallbackObject())); |
| 1596 ASSERT(callback != NULL); | |
| 1597 ASSERT(callback->getter() != NULL); | 1293 ASSERT(callback->getter() != NULL); |
| 1598 | 1294 |
| 1599 // Tail call to runtime. | 1295 // Tail call to runtime. |
| 1600 // Important invariant in CALLBACKS case: the code above must be | 1296 // Important invariant in CALLBACKS case: the code above must be |
| 1601 // structured to never clobber |receiver| register. | 1297 // structured to never clobber |receiver| register. |
| 1602 __ li(scratch2, Handle<AccessorInfo>(callback)); | 1298 __ li(scratch2, callback); |
| 1603 // holder_reg is either receiver or scratch1. | 1299 // holder_reg is either receiver or scratch1. |
| 1604 if (!receiver.is(holder_reg)) { | 1300 if (!receiver.is(holder_reg)) { |
| 1605 ASSERT(scratch1.is(holder_reg)); | 1301 ASSERT(scratch1.is(holder_reg)); |
| 1606 __ Push(receiver, holder_reg); | 1302 __ Push(receiver, holder_reg); |
| 1607 __ lw(scratch3, | 1303 __ lw(scratch3, |
| 1608 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); | 1304 FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); |
| 1609 __ Push(scratch3, scratch2, name_reg); | 1305 __ Push(scratch3, scratch2, name_reg); |
| 1610 } else { | 1306 } else { |
| 1611 __ push(receiver); | 1307 __ push(receiver); |
| 1612 __ lw(scratch3, | 1308 __ lw(scratch3, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1635 } | 1331 } |
| 1636 | 1332 |
| 1637 | 1333 |
| 1638 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { | 1334 void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { |
| 1639 if (kind_ == Code::KEYED_CALL_IC) { | 1335 if (kind_ == Code::KEYED_CALL_IC) { |
| 1640 __ Branch(miss, ne, a2, Operand(name)); | 1336 __ Branch(miss, ne, a2, Operand(name)); |
| 1641 } | 1337 } |
| 1642 } | 1338 } |
| 1643 | 1339 |
| 1644 | 1340 |
| 1645 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | 1341 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, |
| 1646 JSObject* holder, | 1342 Handle<JSObject> holder, |
| 1647 String* name, | 1343 Handle<String> name, |
| 1648 Label* miss) { | 1344 Label* miss) { |
| 1649 ASSERT(holder->IsGlobalObject()); | 1345 ASSERT(holder->IsGlobalObject()); |
| 1650 | 1346 |
| 1651 // Get the number of arguments. | 1347 // Get the number of arguments. |
| 1652 const int argc = arguments().immediate(); | 1348 const int argc = arguments().immediate(); |
| 1653 | 1349 |
| 1654 // Get the receiver from the stack. | 1350 // Get the receiver from the stack. |
| 1655 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 1351 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 1656 | 1352 |
| 1657 // If the object is the holder then we know that it's a global | 1353 // If the object is the holder then we know that it's a global |
| 1658 // object which can only happen for contextual calls. In this case, | 1354 // object which can only happen for contextual calls. In this case, |
| 1659 // the receiver cannot be a smi. | 1355 // the receiver cannot be a smi. |
| 1660 if (object != holder) { | 1356 if (!object.is_identical_to(holder)) { |
| 1661 __ JumpIfSmi(a0, miss); | 1357 __ JumpIfSmi(a0, miss); |
| 1662 } | 1358 } |
| 1663 | 1359 |
| 1664 // Check that the maps haven't changed. | 1360 // Check that the maps haven't changed. |
| 1665 CheckPrototypes(object, a0, holder, a3, a1, t0, name, miss); | 1361 CheckPrototypes(object, a0, holder, a3, a1, t0, name, miss); |
| 1666 } | 1362 } |
| 1667 | 1363 |
| 1668 | 1364 |
| 1669 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | 1365 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1670 JSFunction* function, | 1366 Handle<JSGlobalPropertyCell> cell, |
| 1671 Label* miss) { | 1367 Handle<JSFunction> function, |
| 1368 Label* miss) { |
| 1672 // Get the value from the cell. | 1369 // Get the value from the cell. |
| 1673 __ li(a3, Operand(Handle<JSGlobalPropertyCell>(cell))); | 1370 __ li(a3, Operand(cell)); |
| 1674 __ lw(a1, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); | 1371 __ lw(a1, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); |
| 1675 | 1372 |
| 1676 // Check that the cell contains the same function. | 1373 // Check that the cell contains the same function. |
| 1677 if (heap()->InNewSpace(function)) { | 1374 if (heap()->InNewSpace(*function)) { |
| 1678 // We can't embed a pointer to a function in new space so we have | 1375 // We can't embed a pointer to a function in new space so we have |
| 1679 // to verify that the shared function info is unchanged. This has | 1376 // to verify that the shared function info is unchanged. This has |
| 1680 // the nice side effect that multiple closures based on the same | 1377 // the nice side effect that multiple closures based on the same |
| 1681 // function can all use this call IC. Before we load through the | 1378 // function can all use this call IC. Before we load through the |
| 1682 // function, we have to verify that it still is a function. | 1379 // function, we have to verify that it still is a function. |
| 1683 __ JumpIfSmi(a1, miss); | 1380 __ JumpIfSmi(a1, miss); |
| 1684 __ GetObjectType(a1, a3, a3); | 1381 __ GetObjectType(a1, a3, a3); |
| 1685 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | 1382 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 1686 | 1383 |
| 1687 // Check the shared function info. Make sure it hasn't changed. | 1384 // Check the shared function info. Make sure it hasn't changed. |
| 1688 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); | 1385 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); |
| 1689 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1386 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1690 __ Branch(miss, ne, t0, Operand(a3)); | 1387 __ Branch(miss, ne, t0, Operand(a3)); |
| 1691 } else { | 1388 } else { |
| 1692 __ Branch(miss, ne, a1, Operand(Handle<JSFunction>(function))); | 1389 __ Branch(miss, ne, a1, Operand(function)); |
| 1693 } | 1390 } |
| 1694 } | 1391 } |
| 1695 | 1392 |
| 1696 | 1393 |
| 1697 void CallStubCompiler::GenerateMissBranch() { | 1394 void CallStubCompiler::GenerateMissBranch() { |
| 1698 Handle<Code> code = | 1395 Handle<Code> code = |
| 1699 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1396 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1700 kind_, | 1397 kind_, |
| 1701 extra_state_); | 1398 extra_state_); |
| 1702 __ Jump(code, RelocInfo::CODE_TARGET); | 1399 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1703 } | 1400 } |
| 1704 | 1401 |
| 1705 | 1402 |
| 1706 // TODO(kmillikin): Eliminate this function when the stub cache is fully | |
| 1707 // handlified. | |
| 1708 MaybeObject* CallStubCompiler::TryGenerateMissBranch() { | |
| 1709 MaybeObject* maybe_obj = | |
| 1710 isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), | |
| 1711 kind_, | |
| 1712 extra_state_); | |
| 1713 Object* obj; | |
| 1714 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 1715 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | |
| 1716 return obj; | |
| 1717 } | |
| 1718 | |
| 1719 | |
| 1720 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1403 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1721 Handle<JSObject> holder, | 1404 Handle<JSObject> holder, |
| 1722 int index, | 1405 int index, |
| 1723 Handle<String> name) { | 1406 Handle<String> name) { |
| 1724 // ----------- S t a t e ------------- | 1407 // ----------- S t a t e ------------- |
| 1725 // -- a2 : name | 1408 // -- a2 : name |
| 1726 // -- ra : return address | 1409 // -- ra : return address |
| 1727 // ----------------------------------- | 1410 // ----------------------------------- |
| 1728 Label miss; | 1411 Label miss; |
| 1729 | 1412 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1744 | 1427 |
| 1745 // Handle call cache miss. | 1428 // Handle call cache miss. |
| 1746 __ bind(&miss); | 1429 __ bind(&miss); |
| 1747 GenerateMissBranch(); | 1430 GenerateMissBranch(); |
| 1748 | 1431 |
| 1749 // Return the generated code. | 1432 // Return the generated code. |
| 1750 return GetCode(FIELD, name); | 1433 return GetCode(FIELD, name); |
| 1751 } | 1434 } |
| 1752 | 1435 |
| 1753 | 1436 |
| 1754 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1437 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1755 JSObject* holder, | 1438 Handle<Object> object, |
| 1756 JSGlobalPropertyCell* cell, | 1439 Handle<JSObject> holder, |
| 1757 JSFunction* function, | 1440 Handle<JSGlobalPropertyCell> cell, |
| 1758 String* name) { | 1441 Handle<JSFunction> function, |
| 1442 Handle<String> name) { |
| 1759 // ----------- S t a t e ------------- | 1443 // ----------- S t a t e ------------- |
| 1760 // -- a2 : name | 1444 // -- a2 : name |
| 1761 // -- ra : return address | 1445 // -- ra : return address |
| 1762 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1446 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1763 // -- ... | 1447 // -- ... |
| 1764 // -- sp[argc * 4] : receiver | 1448 // -- sp[argc * 4] : receiver |
| 1765 // ----------------------------------- | 1449 // ----------------------------------- |
| 1766 | 1450 |
| 1767 // If object is not an array, bail out to regular call. | 1451 // If object is not an array, bail out to regular call. |
| 1768 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1452 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1769 | 1453 |
| 1770 Label miss; | 1454 Label miss; |
| 1771 | 1455 |
| 1772 GenerateNameCheck(Handle<String>(name), &miss); | 1456 GenerateNameCheck(name, &miss); |
| 1773 | 1457 |
| 1774 Register receiver = a1; | 1458 Register receiver = a1; |
| 1775 | 1459 |
| 1776 // Get the receiver from the stack. | 1460 // Get the receiver from the stack. |
| 1777 const int argc = arguments().immediate(); | 1461 const int argc = arguments().immediate(); |
| 1778 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1462 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1779 | 1463 |
| 1780 // Check that the receiver isn't a smi. | 1464 // Check that the receiver isn't a smi. |
| 1781 __ JumpIfSmi(receiver, &miss); | 1465 __ JumpIfSmi(receiver, &miss); |
| 1782 | 1466 |
| 1783 // Check that the maps haven't changed. | 1467 // Check that the maps haven't changed. |
| 1784 CheckPrototypes(JSObject::cast(object), receiver, | 1468 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, a3, v0, t0, |
| 1785 holder, a3, v0, t0, name, &miss); | 1469 name, &miss); |
| 1786 | 1470 |
| 1787 if (argc == 0) { | 1471 if (argc == 0) { |
| 1788 // Nothing to do, just return the length. | 1472 // Nothing to do, just return the length. |
| 1789 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1473 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1790 __ Drop(argc + 1); | 1474 __ Drop(argc + 1); |
| 1791 __ Ret(); | 1475 __ Ret(); |
| 1792 } else { | 1476 } else { |
| 1793 Label call_builtin; | 1477 Label call_builtin; |
| 1794 | |
| 1795 Register elements = a3; | 1478 Register elements = a3; |
| 1796 Register end_elements = t1; | 1479 Register end_elements = t1; |
| 1797 | |
| 1798 // Get the elements array of the object. | 1480 // Get the elements array of the object. |
| 1799 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1481 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1800 | 1482 |
| 1801 // Check that the elements are in fast mode and writable. | 1483 // Check that the elements are in fast mode and writable. |
| 1802 __ CheckMap(elements, | 1484 __ CheckMap(elements, |
| 1803 v0, | 1485 v0, |
| 1804 Heap::kFixedArrayMapRootIndex, | 1486 Heap::kFixedArrayMapRootIndex, |
| 1805 &call_builtin, | 1487 &call_builtin, |
| 1806 DONT_DO_SMI_CHECK); | 1488 DONT_DO_SMI_CHECK); |
| 1807 | 1489 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 } | 1610 } |
| 1929 __ bind(&call_builtin); | 1611 __ bind(&call_builtin); |
| 1930 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, | 1612 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, |
| 1931 masm()->isolate()), | 1613 masm()->isolate()), |
| 1932 argc + 1, | 1614 argc + 1, |
| 1933 1); | 1615 1); |
| 1934 } | 1616 } |
| 1935 | 1617 |
| 1936 // Handle call cache miss. | 1618 // Handle call cache miss. |
| 1937 __ bind(&miss); | 1619 __ bind(&miss); |
| 1938 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1620 GenerateMissBranch(); |
| 1939 if (maybe_result->IsFailure()) return maybe_result; | |
| 1940 | 1621 |
| 1941 // Return the generated code. | 1622 // Return the generated code. |
| 1942 return TryGetCode(function); | 1623 return GetCode(function); |
| 1943 } | 1624 } |
| 1944 | 1625 |
| 1945 | 1626 |
| 1946 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1627 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1947 JSObject* holder, | 1628 Handle<Object> object, |
| 1948 JSGlobalPropertyCell* cell, | 1629 Handle<JSObject> holder, |
| 1949 JSFunction* function, | 1630 Handle<JSGlobalPropertyCell> cell, |
| 1950 String* name) { | 1631 Handle<JSFunction> function, |
| 1632 Handle<String> name) { |
| 1951 // ----------- S t a t e ------------- | 1633 // ----------- S t a t e ------------- |
| 1952 // -- a2 : name | 1634 // -- a2 : name |
| 1953 // -- ra : return address | 1635 // -- ra : return address |
| 1954 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1636 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 1955 // -- ... | 1637 // -- ... |
| 1956 // -- sp[argc * 4] : receiver | 1638 // -- sp[argc * 4] : receiver |
| 1957 // ----------------------------------- | 1639 // ----------------------------------- |
| 1958 | 1640 |
| 1959 // If object is not an array, bail out to regular call. | 1641 // If object is not an array, bail out to regular call. |
| 1960 if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value(); | 1642 if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); |
| 1961 | 1643 |
| 1962 Label miss, return_undefined, call_builtin; | 1644 Label miss, return_undefined, call_builtin; |
| 1963 | |
| 1964 Register receiver = a1; | 1645 Register receiver = a1; |
| 1965 Register elements = a3; | 1646 Register elements = a3; |
| 1966 | 1647 GenerateNameCheck(name, &miss); |
| 1967 GenerateNameCheck(Handle<String>(name), &miss); | |
| 1968 | 1648 |
| 1969 // Get the receiver from the stack. | 1649 // Get the receiver from the stack. |
| 1970 const int argc = arguments().immediate(); | 1650 const int argc = arguments().immediate(); |
| 1971 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1651 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 1972 | |
| 1973 // Check that the receiver isn't a smi. | 1652 // Check that the receiver isn't a smi. |
| 1974 __ JumpIfSmi(receiver, &miss); | 1653 __ JumpIfSmi(receiver, &miss); |
| 1975 | 1654 |
| 1976 // Check that the maps haven't changed. | 1655 // Check that the maps haven't changed. |
| 1977 CheckPrototypes(JSObject::cast(object), | 1656 CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, |
| 1978 receiver, holder, elements, t0, v0, name, &miss); | 1657 t0, v0, name, &miss); |
| 1979 | 1658 |
| 1980 // Get the elements array of the object. | 1659 // Get the elements array of the object. |
| 1981 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1660 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1982 | 1661 |
| 1983 // Check that the elements are in fast mode and writable. | 1662 // Check that the elements are in fast mode and writable. |
| 1984 __ CheckMap(elements, | 1663 __ CheckMap(elements, |
| 1985 v0, | 1664 v0, |
| 1986 Heap::kFixedArrayMapRootIndex, | 1665 Heap::kFixedArrayMapRootIndex, |
| 1987 &call_builtin, | 1666 &call_builtin, |
| 1988 DONT_DO_SMI_CHECK); | 1667 DONT_DO_SMI_CHECK); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2017 __ Ret(); | 1696 __ Ret(); |
| 2018 | 1697 |
| 2019 __ bind(&call_builtin); | 1698 __ bind(&call_builtin); |
| 2020 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, | 1699 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, |
| 2021 masm()->isolate()), | 1700 masm()->isolate()), |
| 2022 argc + 1, | 1701 argc + 1, |
| 2023 1); | 1702 1); |
| 2024 | 1703 |
| 2025 // Handle call cache miss. | 1704 // Handle call cache miss. |
| 2026 __ bind(&miss); | 1705 __ bind(&miss); |
| 2027 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1706 GenerateMissBranch(); |
| 2028 if (maybe_result->IsFailure()) return maybe_result; | |
| 2029 | 1707 |
| 2030 // Return the generated code. | 1708 // Return the generated code. |
| 2031 return TryGetCode(function); | 1709 return GetCode(function); |
| 2032 } | 1710 } |
| 2033 | 1711 |
| 2034 | 1712 |
| 2035 MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( | 1713 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2036 Object* object, | 1714 Handle<Object> object, |
| 2037 JSObject* holder, | 1715 Handle<JSObject> holder, |
| 2038 JSGlobalPropertyCell* cell, | 1716 Handle<JSGlobalPropertyCell> cell, |
| 2039 JSFunction* function, | 1717 Handle<JSFunction> function, |
| 2040 String* name) { | 1718 Handle<String> name) { |
| 2041 // ----------- S t a t e ------------- | 1719 // ----------- S t a t e ------------- |
| 2042 // -- a2 : function name | 1720 // -- a2 : function name |
| 2043 // -- ra : return address | 1721 // -- ra : return address |
| 2044 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1722 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2045 // -- ... | 1723 // -- ... |
| 2046 // -- sp[argc * 4] : receiver | 1724 // -- sp[argc * 4] : receiver |
| 2047 // ----------------------------------- | 1725 // ----------------------------------- |
| 2048 | 1726 |
| 2049 // If object is not a string, bail out to regular call. | 1727 // If object is not a string, bail out to regular call. |
| 2050 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1728 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2051 | 1729 |
| 2052 const int argc = arguments().immediate(); | 1730 const int argc = arguments().immediate(); |
| 2053 | |
| 2054 Label miss; | 1731 Label miss; |
| 2055 Label name_miss; | 1732 Label name_miss; |
| 2056 Label index_out_of_range; | 1733 Label index_out_of_range; |
| 2057 | 1734 |
| 2058 Label* index_out_of_range_label = &index_out_of_range; | 1735 Label* index_out_of_range_label = &index_out_of_range; |
| 2059 | 1736 |
| 2060 if (kind_ == Code::CALL_IC && | 1737 if (kind_ == Code::CALL_IC && |
| 2061 (CallICBase::StringStubState::decode(extra_state_) == | 1738 (CallICBase::StringStubState::decode(extra_state_) == |
| 2062 DEFAULT_STRING_STUB)) { | 1739 DEFAULT_STRING_STUB)) { |
| 2063 index_out_of_range_label = &miss; | 1740 index_out_of_range_label = &miss; |
| 2064 } | 1741 } |
| 2065 | 1742 |
| 2066 GenerateNameCheck(Handle<String>(name), &name_miss); | 1743 GenerateNameCheck(name, &name_miss); |
| 2067 | 1744 |
| 2068 // Check that the maps starting from the prototype haven't changed. | 1745 // Check that the maps starting from the prototype haven't changed. |
| 2069 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1746 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2070 Context::STRING_FUNCTION_INDEX, | 1747 Context::STRING_FUNCTION_INDEX, |
| 2071 v0, | 1748 v0, |
| 2072 &miss); | 1749 &miss); |
| 2073 ASSERT(object != holder); | 1750 ASSERT(!object.is_identical_to(holder)); |
| 2074 CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder, | 1751 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2075 a1, a3, t0, name, &miss); | 1752 v0, holder, a1, a3, t0, name, &miss); |
| 2076 | 1753 |
| 2077 Register receiver = a1; | 1754 Register receiver = a1; |
| 2078 Register index = t1; | 1755 Register index = t1; |
| 2079 Register scratch = a3; | 1756 Register scratch = a3; |
| 2080 Register result = v0; | 1757 Register result = v0; |
| 2081 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1758 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2082 if (argc > 0) { | 1759 if (argc > 0) { |
| 2083 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1760 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2084 } else { | 1761 } else { |
| 2085 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1762 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2086 } | 1763 } |
| 2087 | 1764 |
| 2088 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1765 StringCharCodeAtGenerator generator(receiver, |
| 2089 index, | 1766 index, |
| 2090 scratch, | 1767 scratch, |
| 2091 result, | 1768 result, |
| 2092 &miss, // When not a string. | 1769 &miss, // When not a string. |
| 2093 &miss, // When not a number. | 1770 &miss, // When not a number. |
| 2094 index_out_of_range_label, | 1771 index_out_of_range_label, |
| 2095 STRING_INDEX_IS_NUMBER); | 1772 STRING_INDEX_IS_NUMBER); |
| 2096 char_code_at_generator.GenerateFast(masm()); | 1773 generator.GenerateFast(masm()); |
| 2097 __ Drop(argc + 1); | 1774 __ Drop(argc + 1); |
| 2098 __ Ret(); | 1775 __ Ret(); |
| 2099 | 1776 |
| 2100 StubRuntimeCallHelper call_helper; | 1777 StubRuntimeCallHelper call_helper; |
| 2101 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1778 generator.GenerateSlow(masm(), call_helper); |
| 2102 | 1779 |
| 2103 if (index_out_of_range.is_linked()) { | 1780 if (index_out_of_range.is_linked()) { |
| 2104 __ bind(&index_out_of_range); | 1781 __ bind(&index_out_of_range); |
| 2105 __ LoadRoot(v0, Heap::kNanValueRootIndex); | 1782 __ LoadRoot(v0, Heap::kNanValueRootIndex); |
| 2106 __ Drop(argc + 1); | 1783 __ Drop(argc + 1); |
| 2107 __ Ret(); | 1784 __ Ret(); |
| 2108 } | 1785 } |
| 2109 | 1786 |
| 2110 __ bind(&miss); | 1787 __ bind(&miss); |
| 2111 // Restore function name in a2. | 1788 // Restore function name in a2. |
| 2112 __ li(a2, Handle<String>(name)); | 1789 __ li(a2, name); |
| 2113 __ bind(&name_miss); | 1790 __ bind(&name_miss); |
| 2114 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1791 GenerateMissBranch(); |
| 2115 if (maybe_result->IsFailure()) return maybe_result; | |
| 2116 | 1792 |
| 2117 // Return the generated code. | 1793 // Return the generated code. |
| 2118 return TryGetCode(function); | 1794 return GetCode(function); |
| 2119 } | 1795 } |
| 2120 | 1796 |
| 2121 | 1797 |
| 2122 MaybeObject* CallStubCompiler::CompileStringCharAtCall( | 1798 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2123 Object* object, | 1799 Handle<Object> object, |
| 2124 JSObject* holder, | 1800 Handle<JSObject> holder, |
| 2125 JSGlobalPropertyCell* cell, | 1801 Handle<JSGlobalPropertyCell> cell, |
| 2126 JSFunction* function, | 1802 Handle<JSFunction> function, |
| 2127 String* name) { | 1803 Handle<String> name) { |
| 2128 // ----------- S t a t e ------------- | 1804 // ----------- S t a t e ------------- |
| 2129 // -- a2 : function name | 1805 // -- a2 : function name |
| 2130 // -- ra : return address | 1806 // -- ra : return address |
| 2131 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1807 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2132 // -- ... | 1808 // -- ... |
| 2133 // -- sp[argc * 4] : receiver | 1809 // -- sp[argc * 4] : receiver |
| 2134 // ----------------------------------- | 1810 // ----------------------------------- |
| 2135 | 1811 |
| 2136 // If object is not a string, bail out to regular call. | 1812 // If object is not a string, bail out to regular call. |
| 2137 if (!object->IsString() || cell != NULL) return heap()->undefined_value(); | 1813 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2138 | 1814 |
| 2139 const int argc = arguments().immediate(); | 1815 const int argc = arguments().immediate(); |
| 2140 | |
| 2141 Label miss; | 1816 Label miss; |
| 2142 Label name_miss; | 1817 Label name_miss; |
| 2143 Label index_out_of_range; | 1818 Label index_out_of_range; |
| 2144 Label* index_out_of_range_label = &index_out_of_range; | 1819 Label* index_out_of_range_label = &index_out_of_range; |
| 2145 | |
| 2146 if (kind_ == Code::CALL_IC && | 1820 if (kind_ == Code::CALL_IC && |
| 2147 (CallICBase::StringStubState::decode(extra_state_) == | 1821 (CallICBase::StringStubState::decode(extra_state_) == |
| 2148 DEFAULT_STRING_STUB)) { | 1822 DEFAULT_STRING_STUB)) { |
| 2149 index_out_of_range_label = &miss; | 1823 index_out_of_range_label = &miss; |
| 2150 } | 1824 } |
| 2151 | 1825 GenerateNameCheck(name, &name_miss); |
| 2152 GenerateNameCheck(Handle<String>(name), &name_miss); | |
| 2153 | 1826 |
| 2154 // Check that the maps starting from the prototype haven't changed. | 1827 // Check that the maps starting from the prototype haven't changed. |
| 2155 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1828 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2156 Context::STRING_FUNCTION_INDEX, | 1829 Context::STRING_FUNCTION_INDEX, |
| 2157 v0, | 1830 v0, |
| 2158 &miss); | 1831 &miss); |
| 2159 ASSERT(object != holder); | 1832 ASSERT(!object.is_identical_to(holder)); |
| 2160 CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder, | 1833 CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2161 a1, a3, t0, name, &miss); | 1834 v0, holder, a1, a3, t0, name, &miss); |
| 2162 | 1835 |
| 2163 Register receiver = v0; | 1836 Register receiver = v0; |
| 2164 Register index = t1; | 1837 Register index = t1; |
| 2165 Register scratch1 = a1; | 1838 Register scratch1 = a1; |
| 2166 Register scratch2 = a3; | 1839 Register scratch2 = a3; |
| 2167 Register result = v0; | 1840 Register result = v0; |
| 2168 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1841 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2169 if (argc > 0) { | 1842 if (argc > 0) { |
| 2170 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1843 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2171 } else { | 1844 } else { |
| 2172 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1845 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2173 } | 1846 } |
| 2174 | 1847 |
| 2175 StringCharAtGenerator char_at_generator(receiver, | 1848 StringCharAtGenerator generator(receiver, |
| 2176 index, | 1849 index, |
| 2177 scratch1, | 1850 scratch1, |
| 2178 scratch2, | 1851 scratch2, |
| 2179 result, | 1852 result, |
| 2180 &miss, // When not a string. | 1853 &miss, // When not a string. |
| 2181 &miss, // When not a number. | 1854 &miss, // When not a number. |
| 2182 index_out_of_range_label, | 1855 index_out_of_range_label, |
| 2183 STRING_INDEX_IS_NUMBER); | 1856 STRING_INDEX_IS_NUMBER); |
| 2184 char_at_generator.GenerateFast(masm()); | 1857 generator.GenerateFast(masm()); |
| 2185 __ Drop(argc + 1); | 1858 __ Drop(argc + 1); |
| 2186 __ Ret(); | 1859 __ Ret(); |
| 2187 | 1860 |
| 2188 StubRuntimeCallHelper call_helper; | 1861 StubRuntimeCallHelper call_helper; |
| 2189 char_at_generator.GenerateSlow(masm(), call_helper); | 1862 generator.GenerateSlow(masm(), call_helper); |
| 2190 | 1863 |
| 2191 if (index_out_of_range.is_linked()) { | 1864 if (index_out_of_range.is_linked()) { |
| 2192 __ bind(&index_out_of_range); | 1865 __ bind(&index_out_of_range); |
| 2193 __ LoadRoot(v0, Heap::kEmptyStringRootIndex); | 1866 __ LoadRoot(v0, Heap::kEmptyStringRootIndex); |
| 2194 __ Drop(argc + 1); | 1867 __ Drop(argc + 1); |
| 2195 __ Ret(); | 1868 __ Ret(); |
| 2196 } | 1869 } |
| 2197 | 1870 |
| 2198 __ bind(&miss); | 1871 __ bind(&miss); |
| 2199 // Restore function name in a2. | 1872 // Restore function name in a2. |
| 2200 __ li(a2, Handle<String>(name)); | 1873 __ li(a2, name); |
| 2201 __ bind(&name_miss); | 1874 __ bind(&name_miss); |
| 2202 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1875 GenerateMissBranch(); |
| 2203 if (maybe_result->IsFailure()) return maybe_result; | |
| 2204 | 1876 |
| 2205 // Return the generated code. | 1877 // Return the generated code. |
| 2206 return TryGetCode(function); | 1878 return GetCode(function); |
| 2207 } | 1879 } |
| 2208 | 1880 |
| 2209 | 1881 |
| 2210 MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( | 1882 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2211 Object* object, | 1883 Handle<Object> object, |
| 2212 JSObject* holder, | 1884 Handle<JSObject> holder, |
| 2213 JSGlobalPropertyCell* cell, | 1885 Handle<JSGlobalPropertyCell> cell, |
| 2214 JSFunction* function, | 1886 Handle<JSFunction> function, |
| 2215 String* name) { | 1887 Handle<String> name) { |
| 2216 // ----------- S t a t e ------------- | 1888 // ----------- S t a t e ------------- |
| 2217 // -- a2 : function name | 1889 // -- a2 : function name |
| 2218 // -- ra : return address | 1890 // -- ra : return address |
| 2219 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1891 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2220 // -- ... | 1892 // -- ... |
| 2221 // -- sp[argc * 4] : receiver | 1893 // -- sp[argc * 4] : receiver |
| 2222 // ----------------------------------- | 1894 // ----------------------------------- |
| 2223 | 1895 |
| 2224 const int argc = arguments().immediate(); | 1896 const int argc = arguments().immediate(); |
| 2225 | 1897 |
| 2226 // If the object is not a JSObject or we got an unexpected number of | 1898 // If the object is not a JSObject or we got an unexpected number of |
| 2227 // arguments, bail out to the regular call. | 1899 // arguments, bail out to the regular call. |
| 2228 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1900 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2229 | 1901 |
| 2230 Label miss; | 1902 Label miss; |
| 2231 GenerateNameCheck(Handle<String>(name), &miss); | 1903 GenerateNameCheck(name, &miss); |
| 2232 | 1904 |
| 2233 if (cell == NULL) { | 1905 if (cell.is_null()) { |
| 2234 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 1906 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
| 2235 | 1907 |
| 2236 STATIC_ASSERT(kSmiTag == 0); | 1908 STATIC_ASSERT(kSmiTag == 0); |
| 2237 __ JumpIfSmi(a1, &miss); | 1909 __ JumpIfSmi(a1, &miss); |
| 2238 | 1910 |
| 2239 CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name, | 1911 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0, |
| 2240 &miss); | 1912 name, &miss); |
| 2241 } else { | 1913 } else { |
| 2242 ASSERT(cell->value() == function); | 1914 ASSERT(cell->value() == *function); |
| 2243 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1915 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1916 &miss); |
| 2244 GenerateLoadFunctionFromCell(cell, function, &miss); | 1917 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2245 } | 1918 } |
| 2246 | 1919 |
| 2247 // Load the char code argument. | 1920 // Load the char code argument. |
| 2248 Register code = a1; | 1921 Register code = a1; |
| 2249 __ lw(code, MemOperand(sp, 0 * kPointerSize)); | 1922 __ lw(code, MemOperand(sp, 0 * kPointerSize)); |
| 2250 | 1923 |
| 2251 // Check the code is a smi. | 1924 // Check the code is a smi. |
| 2252 Label slow; | 1925 Label slow; |
| 2253 STATIC_ASSERT(kSmiTag == 0); | 1926 STATIC_ASSERT(kSmiTag == 0); |
| 2254 __ JumpIfNotSmi(code, &slow); | 1927 __ JumpIfNotSmi(code, &slow); |
| 2255 | 1928 |
| 2256 // Convert the smi code to uint16. | 1929 // Convert the smi code to uint16. |
| 2257 __ And(code, code, Operand(Smi::FromInt(0xffff))); | 1930 __ And(code, code, Operand(Smi::FromInt(0xffff))); |
| 2258 | 1931 |
| 2259 StringCharFromCodeGenerator char_from_code_generator(code, v0); | 1932 StringCharFromCodeGenerator generator(code, v0); |
| 2260 char_from_code_generator.GenerateFast(masm()); | 1933 generator.GenerateFast(masm()); |
| 2261 __ Drop(argc + 1); | 1934 __ Drop(argc + 1); |
| 2262 __ Ret(); | 1935 __ Ret(); |
| 2263 | 1936 |
| 2264 StubRuntimeCallHelper call_helper; | 1937 StubRuntimeCallHelper call_helper; |
| 2265 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1938 generator.GenerateSlow(masm(), call_helper); |
| 2266 | 1939 |
| 2267 // Tail call the full function. We do not have to patch the receiver | 1940 // Tail call the full function. We do not have to patch the receiver |
| 2268 // because the function makes no use of it. | 1941 // because the function makes no use of it. |
| 2269 __ bind(&slow); | 1942 __ bind(&slow); |
| 2270 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 1943 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2271 | 1944 |
| 2272 __ bind(&miss); | 1945 __ bind(&miss); |
| 2273 // a2: function name. | 1946 // a2: function name. |
| 2274 MaybeObject* maybe_result = TryGenerateMissBranch(); | 1947 GenerateMissBranch(); |
| 2275 if (maybe_result->IsFailure()) return maybe_result; | |
| 2276 | 1948 |
| 2277 // Return the generated code. | 1949 // Return the generated code. |
| 2278 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 1950 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2279 } | 1951 } |
| 2280 | 1952 |
| 2281 | 1953 |
| 2282 MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, | 1954 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2283 JSObject* holder, | 1955 Handle<Object> object, |
| 2284 JSGlobalPropertyCell* cell, | 1956 Handle<JSObject> holder, |
| 2285 JSFunction* function, | 1957 Handle<JSGlobalPropertyCell> cell, |
| 2286 String* name) { | 1958 Handle<JSFunction> function, |
| 1959 Handle<String> name) { |
| 2287 // ----------- S t a t e ------------- | 1960 // ----------- S t a t e ------------- |
| 2288 // -- a2 : function name | 1961 // -- a2 : function name |
| 2289 // -- ra : return address | 1962 // -- ra : return address |
| 2290 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 1963 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2291 // -- ... | 1964 // -- ... |
| 2292 // -- sp[argc * 4] : receiver | 1965 // -- sp[argc * 4] : receiver |
| 2293 // ----------------------------------- | 1966 // ----------------------------------- |
| 2294 | 1967 |
| 2295 if (!CpuFeatures::IsSupported(FPU)) | 1968 if (!CpuFeatures::IsSupported(FPU)) { |
| 2296 return heap()->undefined_value(); | 1969 return Handle<Code>::null(); |
| 1970 } |
| 1971 |
| 2297 CpuFeatures::Scope scope_fpu(FPU); | 1972 CpuFeatures::Scope scope_fpu(FPU); |
| 2298 | |
| 2299 const int argc = arguments().immediate(); | 1973 const int argc = arguments().immediate(); |
| 2300 | |
| 2301 // If the object is not a JSObject or we got an unexpected number of | 1974 // If the object is not a JSObject or we got an unexpected number of |
| 2302 // arguments, bail out to the regular call. | 1975 // arguments, bail out to the regular call. |
| 2303 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 1976 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2304 | 1977 |
| 2305 Label miss, slow; | 1978 Label miss, slow; |
| 2306 GenerateNameCheck(Handle<String>(name), &miss); | 1979 GenerateNameCheck(name, &miss); |
| 2307 | 1980 |
| 2308 if (cell == NULL) { | 1981 if (cell.is_null()) { |
| 2309 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 1982 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
| 2310 | |
| 2311 STATIC_ASSERT(kSmiTag == 0); | 1983 STATIC_ASSERT(kSmiTag == 0); |
| 2312 __ JumpIfSmi(a1, &miss); | 1984 __ JumpIfSmi(a1, &miss); |
| 2313 | 1985 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, |
| 2314 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, | 1986 name, &miss); |
| 2315 &miss); | |
| 2316 } else { | 1987 } else { |
| 2317 ASSERT(cell->value() == function); | 1988 ASSERT(cell->value() == *function); |
| 2318 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 1989 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1990 &miss); |
| 2319 GenerateLoadFunctionFromCell(cell, function, &miss); | 1991 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2320 } | 1992 } |
| 2321 | 1993 |
| 2322 // Load the (only) argument into v0. | 1994 // Load the (only) argument into v0. |
| 2323 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 1995 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
| 2324 | 1996 |
| 2325 // If the argument is a smi, just return. | 1997 // If the argument is a smi, just return. |
| 2326 STATIC_ASSERT(kSmiTag == 0); | 1998 STATIC_ASSERT(kSmiTag == 0); |
| 2327 __ And(t0, v0, Operand(kSmiTagMask)); | 1999 __ And(t0, v0, Operand(kSmiTagMask)); |
| 2328 __ Drop(argc + 1, eq, t0, Operand(zero_reg)); | 2000 __ Drop(argc + 1, eq, t0, Operand(zero_reg)); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2398 // Restore FCSR and fall to slow case. | 2070 // Restore FCSR and fall to slow case. |
| 2399 __ ctc1(a3, FCSR); | 2071 __ ctc1(a3, FCSR); |
| 2400 | 2072 |
| 2401 __ bind(&slow); | 2073 __ bind(&slow); |
| 2402 // Tail call the full function. We do not have to patch the receiver | 2074 // Tail call the full function. We do not have to patch the receiver |
| 2403 // because the function makes no use of it. | 2075 // because the function makes no use of it. |
| 2404 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2076 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2405 | 2077 |
| 2406 __ bind(&miss); | 2078 __ bind(&miss); |
| 2407 // a2: function name. | 2079 // a2: function name. |
| 2408 MaybeObject* obj = TryGenerateMissBranch(); | 2080 GenerateMissBranch(); |
| 2409 if (obj->IsFailure()) return obj; | |
| 2410 | 2081 |
| 2411 // Return the generated code. | 2082 // Return the generated code. |
| 2412 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2083 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2413 } | 2084 } |
| 2414 | 2085 |
| 2415 | 2086 |
| 2416 MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, | 2087 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2417 JSObject* holder, | 2088 Handle<Object> object, |
| 2418 JSGlobalPropertyCell* cell, | 2089 Handle<JSObject> holder, |
| 2419 JSFunction* function, | 2090 Handle<JSGlobalPropertyCell> cell, |
| 2420 String* name) { | 2091 Handle<JSFunction> function, |
| 2092 Handle<String> name) { |
| 2421 // ----------- S t a t e ------------- | 2093 // ----------- S t a t e ------------- |
| 2422 // -- a2 : function name | 2094 // -- a2 : function name |
| 2423 // -- ra : return address | 2095 // -- ra : return address |
| 2424 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | 2096 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) |
| 2425 // -- ... | 2097 // -- ... |
| 2426 // -- sp[argc * 4] : receiver | 2098 // -- sp[argc * 4] : receiver |
| 2427 // ----------------------------------- | 2099 // ----------------------------------- |
| 2428 | 2100 |
| 2429 const int argc = arguments().immediate(); | 2101 const int argc = arguments().immediate(); |
| 2430 | |
| 2431 // If the object is not a JSObject or we got an unexpected number of | 2102 // If the object is not a JSObject or we got an unexpected number of |
| 2432 // arguments, bail out to the regular call. | 2103 // arguments, bail out to the regular call. |
| 2433 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); | 2104 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2434 | 2105 |
| 2435 Label miss; | 2106 Label miss; |
| 2436 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2437 | 2107 |
| 2438 if (cell == NULL) { | 2108 GenerateNameCheck(name, &miss); |
| 2109 if (cell.is_null()) { |
| 2439 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | 2110 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); |
| 2440 | |
| 2441 STATIC_ASSERT(kSmiTag == 0); | 2111 STATIC_ASSERT(kSmiTag == 0); |
| 2442 __ JumpIfSmi(a1, &miss); | 2112 __ JumpIfSmi(a1, &miss); |
| 2443 | 2113 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0, |
| 2444 CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name, | 2114 name, &miss); |
| 2445 &miss); | |
| 2446 } else { | 2115 } else { |
| 2447 ASSERT(cell->value() == function); | 2116 ASSERT(cell->value() == *function); |
| 2448 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | 2117 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2118 &miss); |
| 2449 GenerateLoadFunctionFromCell(cell, function, &miss); | 2119 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2450 } | 2120 } |
| 2451 | 2121 |
| 2452 // Load the (only) argument into v0. | 2122 // Load the (only) argument into v0. |
| 2453 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2123 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
| 2454 | 2124 |
| 2455 // Check if the argument is a smi. | 2125 // Check if the argument is a smi. |
| 2456 Label not_smi; | 2126 Label not_smi; |
| 2457 STATIC_ASSERT(kSmiTag == 0); | 2127 STATIC_ASSERT(kSmiTag == 0); |
| 2458 __ JumpIfNotSmi(v0, ¬_smi); | 2128 __ JumpIfNotSmi(v0, ¬_smi); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2500 __ Drop(argc + 1); | 2170 __ Drop(argc + 1); |
| 2501 __ Ret(); | 2171 __ Ret(); |
| 2502 | 2172 |
| 2503 // Tail call the full function. We do not have to patch the receiver | 2173 // Tail call the full function. We do not have to patch the receiver |
| 2504 // because the function makes no use of it. | 2174 // because the function makes no use of it. |
| 2505 __ bind(&slow); | 2175 __ bind(&slow); |
| 2506 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); | 2176 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2507 | 2177 |
| 2508 __ bind(&miss); | 2178 __ bind(&miss); |
| 2509 // a2: function name. | 2179 // a2: function name. |
| 2510 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2180 GenerateMissBranch(); |
| 2511 if (maybe_result->IsFailure()) return maybe_result; | |
| 2512 | 2181 |
| 2513 // Return the generated code. | 2182 // Return the generated code. |
| 2514 return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); | 2183 return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); |
| 2515 } | 2184 } |
| 2516 | 2185 |
| 2517 | 2186 |
| 2518 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2187 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2519 const CallOptimization& optimization, | 2188 const CallOptimization& optimization, |
| 2520 Object* object, | 2189 Handle<Object> object, |
| 2521 JSObject* holder, | 2190 Handle<JSObject> holder, |
| 2522 JSGlobalPropertyCell* cell, | 2191 Handle<JSGlobalPropertyCell> cell, |
| 2523 JSFunction* function, | 2192 Handle<JSFunction> function, |
| 2524 String* name) { | 2193 Handle<String> name) { |
| 2525 | 2194 |
| 2526 Counters* counters = isolate()->counters(); | 2195 Counters* counters = isolate()->counters(); |
| 2527 | 2196 |
| 2528 ASSERT(optimization.is_simple_api_call()); | 2197 ASSERT(optimization.is_simple_api_call()); |
| 2529 // Bail out if object is a global object as we don't want to | 2198 // Bail out if object is a global object as we don't want to |
| 2530 // repatch it to global receiver. | 2199 // repatch it to global receiver. |
| 2531 if (object->IsGlobalObject()) return heap()->undefined_value(); | 2200 if (object->IsGlobalObject()) return Handle<Code>::null(); |
| 2532 if (cell != NULL) return heap()->undefined_value(); | 2201 if (!cell.is_null()) return Handle<Code>::null(); |
| 2533 if (!object->IsJSObject()) return heap()->undefined_value(); | 2202 if (!object->IsJSObject()) return Handle<Code>::null(); |
| 2534 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2203 int depth = optimization.GetPrototypeDepthOfExpectedType( |
| 2535 JSObject::cast(object), holder); | 2204 Handle<JSObject>::cast(object), holder); |
| 2536 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); | 2205 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); |
| 2537 | 2206 |
| 2538 Label miss, miss_before_stack_reserved; | 2207 Label miss, miss_before_stack_reserved; |
| 2539 | 2208 |
| 2540 GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved); | 2209 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2541 | 2210 |
| 2542 // Get the receiver from the stack. | 2211 // Get the receiver from the stack. |
| 2543 const int argc = arguments().immediate(); | 2212 const int argc = arguments().immediate(); |
| 2544 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2213 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2545 | 2214 |
| 2546 // Check that the receiver isn't a smi. | 2215 // Check that the receiver isn't a smi. |
| 2547 __ JumpIfSmi(a1, &miss_before_stack_reserved); | 2216 __ JumpIfSmi(a1, &miss_before_stack_reserved); |
| 2548 | 2217 |
| 2549 __ IncrementCounter(counters->call_const(), 1, a0, a3); | 2218 __ IncrementCounter(counters->call_const(), 1, a0, a3); |
| 2550 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); | 2219 __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); |
| 2551 | 2220 |
| 2552 ReserveSpaceForFastApiCall(masm(), a0); | 2221 ReserveSpaceForFastApiCall(masm(), a0); |
| 2553 | 2222 |
| 2554 // Check that the maps haven't changed and find a Holder as a side effect. | 2223 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2555 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, | 2224 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name, |
| 2556 depth, &miss); | 2225 depth, &miss); |
| 2557 | 2226 |
| 2558 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); | 2227 GenerateFastApiDirectCall(masm(), optimization, argc); |
| 2559 if (result->IsFailure()) return result; | |
| 2560 | 2228 |
| 2561 __ bind(&miss); | 2229 __ bind(&miss); |
| 2562 FreeSpaceForFastApiCall(masm()); | 2230 FreeSpaceForFastApiCall(masm()); |
| 2563 | 2231 |
| 2564 __ bind(&miss_before_stack_reserved); | 2232 __ bind(&miss_before_stack_reserved); |
| 2565 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2233 GenerateMissBranch(); |
| 2566 if (maybe_result->IsFailure()) return maybe_result; | |
| 2567 | 2234 |
| 2568 // Return the generated code. | 2235 // Return the generated code. |
| 2569 return TryGetCode(function); | 2236 return GetCode(function); |
| 2570 } | 2237 } |
| 2571 | 2238 |
| 2572 | 2239 |
| 2573 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, | 2240 Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, |
| 2574 JSObject* holder, | 2241 Handle<JSObject> holder, |
| 2575 JSFunction* function, | 2242 Handle<JSFunction> function, |
| 2576 String* name, | 2243 Handle<String> name, |
| 2577 CheckType check) { | 2244 CheckType check) { |
| 2578 // ----------- S t a t e ------------- | 2245 // ----------- S t a t e ------------- |
| 2579 // -- a2 : name | 2246 // -- a2 : name |
| 2580 // -- ra : return address | 2247 // -- ra : return address |
| 2581 // ----------------------------------- | 2248 // ----------------------------------- |
| 2582 if (HasCustomCallGenerator(function)) { | 2249 if (HasCustomCallGenerator(function)) { |
| 2583 MaybeObject* maybe_result = CompileCustomCall( | 2250 Handle<Code> code = CompileCustomCall(object, holder, |
| 2584 object, holder, NULL, function, name); | 2251 Handle<JSGlobalPropertyCell>::null(), |
| 2585 Object* result; | 2252 function, name); |
| 2586 if (!maybe_result->ToObject(&result)) return maybe_result; | 2253 // A null handle means bail out to the regular compiler code below. |
| 2587 // Undefined means bail out to regular compiler. | 2254 if (!code.is_null()) return code; |
| 2588 if (!result->IsUndefined()) return result; | |
| 2589 } | 2255 } |
| 2590 | 2256 |
| 2591 Label miss; | 2257 Label miss; |
| 2592 | 2258 |
| 2593 GenerateNameCheck(Handle<String>(name), &miss); | 2259 GenerateNameCheck(name, &miss); |
| 2594 | 2260 |
| 2595 // Get the receiver from the stack. | 2261 // Get the receiver from the stack. |
| 2596 const int argc = arguments().immediate(); | 2262 const int argc = arguments().immediate(); |
| 2597 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2263 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2598 | 2264 |
| 2599 // Check that the receiver isn't a smi. | 2265 // Check that the receiver isn't a smi. |
| 2600 if (check != NUMBER_CHECK) { | 2266 if (check != NUMBER_CHECK) { |
| 2601 __ And(t1, a1, Operand(kSmiTagMask)); | 2267 __ And(t1, a1, Operand(kSmiTagMask)); |
| 2602 __ Branch(&miss, eq, t1, Operand(zero_reg)); | 2268 __ Branch(&miss, eq, t1, Operand(zero_reg)); |
| 2603 } | 2269 } |
| 2604 | 2270 |
| 2605 // Make sure that it's okay not to patch the on stack receiver | 2271 // Make sure that it's okay not to patch the on stack receiver |
| 2606 // unless we're doing a receiver map check. | 2272 // unless we're doing a receiver map check. |
| 2607 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2273 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2608 | |
| 2609 SharedFunctionInfo* function_info = function->shared(); | |
| 2610 switch (check) { | 2274 switch (check) { |
| 2611 case RECEIVER_MAP_CHECK: | 2275 case RECEIVER_MAP_CHECK: |
| 2612 __ IncrementCounter(masm()->isolate()->counters()->call_const(), | 2276 __ IncrementCounter(masm()->isolate()->counters()->call_const(), |
| 2613 1, a0, a3); | 2277 1, a0, a3); |
| 2614 | 2278 |
| 2615 // Check that the maps haven't changed. | 2279 // Check that the maps haven't changed. |
| 2616 CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name, | 2280 CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, |
| 2617 &miss); | 2281 name, &miss); |
| 2618 | 2282 |
| 2619 // Patch the receiver on the stack with the global proxy if | 2283 // Patch the receiver on the stack with the global proxy if |
| 2620 // necessary. | 2284 // necessary. |
| 2621 if (object->IsGlobalObject()) { | 2285 if (object->IsGlobalObject()) { |
| 2622 __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | 2286 __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); |
| 2623 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | 2287 __ sw(a3, MemOperand(sp, argc * kPointerSize)); |
| 2624 } | 2288 } |
| 2625 break; | 2289 break; |
| 2626 | 2290 |
| 2627 case STRING_CHECK: | 2291 case STRING_CHECK: |
| 2628 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2292 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2629 // Calling non-strict non-builtins with a value as the receiver | |
| 2630 // requires boxing. | |
| 2631 __ jmp(&miss); | |
| 2632 } else { | |
| 2633 // Check that the object is a two-byte string or a symbol. | 2293 // Check that the object is a two-byte string or a symbol. |
| 2634 __ GetObjectType(a1, a3, a3); | 2294 __ GetObjectType(a1, a3, a3); |
| 2635 __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); | 2295 __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); |
| 2636 // Check that the maps starting from the prototype haven't changed. | 2296 // Check that the maps starting from the prototype haven't changed. |
| 2637 GenerateDirectLoadGlobalFunctionPrototype( | 2297 GenerateDirectLoadGlobalFunctionPrototype( |
| 2638 masm(), Context::STRING_FUNCTION_INDEX, a0, &miss); | 2298 masm(), Context::STRING_FUNCTION_INDEX, a0, &miss); |
| 2639 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, | 2299 CheckPrototypes( |
| 2640 a1, t0, name, &miss); | 2300 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2301 a0, holder, a3, a1, t0, name, &miss); |
| 2302 } else { |
| 2303 // Calling non-strict non-builtins with a value as the receiver |
| 2304 // requires boxing. |
| 2305 __ jmp(&miss); |
| 2641 } | 2306 } |
| 2642 break; | 2307 break; |
| 2643 | 2308 |
| 2644 case NUMBER_CHECK: { | 2309 case NUMBER_CHECK: |
| 2645 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2310 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2646 // Calling non-strict non-builtins with a value as the receiver | |
| 2647 // requires boxing. | |
| 2648 __ jmp(&miss); | |
| 2649 } else { | |
| 2650 Label fast; | 2311 Label fast; |
| 2651 // Check that the object is a smi or a heap number. | 2312 // Check that the object is a smi or a heap number. |
| 2652 __ And(t1, a1, Operand(kSmiTagMask)); | 2313 __ And(t1, a1, Operand(kSmiTagMask)); |
| 2653 __ Branch(&fast, eq, t1, Operand(zero_reg)); | 2314 __ Branch(&fast, eq, t1, Operand(zero_reg)); |
| 2654 __ GetObjectType(a1, a0, a0); | 2315 __ GetObjectType(a1, a0, a0); |
| 2655 __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE)); | 2316 __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE)); |
| 2656 __ bind(&fast); | 2317 __ bind(&fast); |
| 2657 // Check that the maps starting from the prototype haven't changed. | 2318 // Check that the maps starting from the prototype haven't changed. |
| 2658 GenerateDirectLoadGlobalFunctionPrototype( | 2319 GenerateDirectLoadGlobalFunctionPrototype( |
| 2659 masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss); | 2320 masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss); |
| 2660 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, | 2321 CheckPrototypes( |
| 2661 a1, t0, name, &miss); | 2322 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2662 } | 2323 a0, holder, a3, a1, t0, name, &miss); |
| 2663 break; | 2324 } else { |
| 2664 } | |
| 2665 | |
| 2666 case BOOLEAN_CHECK: { | |
| 2667 if (!function->IsBuiltin() && !function_info->strict_mode()) { | |
| 2668 // Calling non-strict non-builtins with a value as the receiver | 2325 // Calling non-strict non-builtins with a value as the receiver |
| 2669 // requires boxing. | 2326 // requires boxing. |
| 2670 __ jmp(&miss); | 2327 __ jmp(&miss); |
| 2671 } else { | 2328 } |
| 2329 break; |
| 2330 |
| 2331 case BOOLEAN_CHECK: |
| 2332 if (function->IsBuiltin() || function->shared()->strict_mode()) { |
| 2672 Label fast; | 2333 Label fast; |
| 2673 // Check that the object is a boolean. | 2334 // Check that the object is a boolean. |
| 2674 __ LoadRoot(t0, Heap::kTrueValueRootIndex); | 2335 __ LoadRoot(t0, Heap::kTrueValueRootIndex); |
| 2675 __ Branch(&fast, eq, a1, Operand(t0)); | 2336 __ Branch(&fast, eq, a1, Operand(t0)); |
| 2676 __ LoadRoot(t0, Heap::kFalseValueRootIndex); | 2337 __ LoadRoot(t0, Heap::kFalseValueRootIndex); |
| 2677 __ Branch(&miss, ne, a1, Operand(t0)); | 2338 __ Branch(&miss, ne, a1, Operand(t0)); |
| 2678 __ bind(&fast); | 2339 __ bind(&fast); |
| 2679 // Check that the maps starting from the prototype haven't changed. | 2340 // Check that the maps starting from the prototype haven't changed. |
| 2680 GenerateDirectLoadGlobalFunctionPrototype( | 2341 GenerateDirectLoadGlobalFunctionPrototype( |
| 2681 masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss); | 2342 masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss); |
| 2682 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, | 2343 CheckPrototypes( |
| 2683 a1, t0, name, &miss); | 2344 Handle<JSObject>(JSObject::cast(object->GetPrototype())), |
| 2345 a0, holder, a3, a1, t0, name, &miss); |
| 2346 } else { |
| 2347 // Calling non-strict non-builtins with a value as the receiver |
| 2348 // requires boxing. |
| 2349 __ jmp(&miss); |
| 2684 } | 2350 } |
| 2685 break; | 2351 break; |
| 2686 } | 2352 } |
| 2687 | 2353 |
| 2688 default: | |
| 2689 UNREACHABLE(); | |
| 2690 } | |
| 2691 | |
| 2692 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2354 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2693 ? CALL_AS_FUNCTION | 2355 ? CALL_AS_FUNCTION |
| 2694 : CALL_AS_METHOD; | 2356 : CALL_AS_METHOD; |
| 2695 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); | 2357 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); |
| 2696 | 2358 |
| 2697 // Handle call cache miss. | 2359 // Handle call cache miss. |
| 2698 __ bind(&miss); | 2360 __ bind(&miss); |
| 2699 | 2361 |
| 2700 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2362 GenerateMissBranch(); |
| 2701 if (maybe_result->IsFailure()) return maybe_result; | |
| 2702 | 2363 |
| 2703 // Return the generated code. | 2364 // Return the generated code. |
| 2704 return TryGetCode(function); | 2365 return GetCode(function); |
| 2705 } | 2366 } |
| 2706 | 2367 |
| 2707 | 2368 |
| 2708 MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 2369 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2709 JSObject* holder, | 2370 Handle<JSObject> holder, |
| 2710 String* name) { | 2371 Handle<String> name) { |
| 2711 // ----------- S t a t e ------------- | 2372 // ----------- S t a t e ------------- |
| 2712 // -- a2 : name | 2373 // -- a2 : name |
| 2713 // -- ra : return address | 2374 // -- ra : return address |
| 2714 // ----------------------------------- | 2375 // ----------------------------------- |
| 2715 | 2376 |
| 2716 Label miss; | 2377 Label miss; |
| 2717 | 2378 |
| 2718 GenerateNameCheck(Handle<String>(name), &miss); | 2379 GenerateNameCheck(name, &miss); |
| 2719 | 2380 |
| 2720 // Get the number of arguments. | 2381 // Get the number of arguments. |
| 2721 const int argc = arguments().immediate(); | 2382 const int argc = arguments().immediate(); |
| 2722 | |
| 2723 LookupResult lookup(isolate()); | 2383 LookupResult lookup(isolate()); |
| 2724 LookupPostInterceptor(holder, name, &lookup); | 2384 LookupPostInterceptor(holder, name, &lookup); |
| 2725 | 2385 |
| 2726 // Get the receiver from the stack. | 2386 // Get the receiver from the stack. |
| 2727 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2387 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2728 | 2388 |
| 2729 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); | 2389 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); |
| 2730 MaybeObject* result = compiler.Compile(masm(), | 2390 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, |
| 2731 object, | 2391 &miss); |
| 2732 holder, | |
| 2733 name, | |
| 2734 &lookup, | |
| 2735 a1, | |
| 2736 a3, | |
| 2737 t0, | |
| 2738 a0, | |
| 2739 &miss); | |
| 2740 if (result->IsFailure()) { | |
| 2741 return result; | |
| 2742 } | |
| 2743 | 2392 |
| 2744 // Move returned value, the function to call, to a1. | 2393 // Move returned value, the function to call, to a1. |
| 2745 __ mov(a1, v0); | 2394 __ mov(a1, v0); |
| 2746 // Restore receiver. | 2395 // Restore receiver. |
| 2747 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 2396 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 2748 | 2397 |
| 2749 GenerateCallFunction(masm(), Handle<Object>(object), arguments(), &miss, | 2398 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); |
| 2750 extra_state_); | |
| 2751 | 2399 |
| 2752 // Handle call cache miss. | 2400 // Handle call cache miss. |
| 2753 __ bind(&miss); | 2401 __ bind(&miss); |
| 2754 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2402 GenerateMissBranch(); |
| 2755 if (maybe_result->IsFailure()) return maybe_result; | |
| 2756 | 2403 |
| 2757 // Return the generated code. | 2404 // Return the generated code. |
| 2758 return TryGetCode(INTERCEPTOR, name); | 2405 return GetCode(INTERCEPTOR, name); |
| 2759 } | 2406 } |
| 2760 | 2407 |
| 2761 | 2408 |
| 2762 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, | 2409 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2763 GlobalObject* holder, | 2410 Handle<JSObject> object, |
| 2764 JSGlobalPropertyCell* cell, | 2411 Handle<GlobalObject> holder, |
| 2765 JSFunction* function, | 2412 Handle<JSGlobalPropertyCell> cell, |
| 2766 String* name) { | 2413 Handle<JSFunction> function, |
| 2414 Handle<String> name) { |
| 2767 // ----------- S t a t e ------------- | 2415 // ----------- S t a t e ------------- |
| 2768 // -- a2 : name | 2416 // -- a2 : name |
| 2769 // -- ra : return address | 2417 // -- ra : return address |
| 2770 // ----------------------------------- | 2418 // ----------------------------------- |
| 2771 | 2419 |
| 2772 if (HasCustomCallGenerator(function)) { | 2420 if (HasCustomCallGenerator(function)) { |
| 2773 MaybeObject* maybe_result = CompileCustomCall( | 2421 Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); |
| 2774 object, holder, cell, function, name); | 2422 // A null handle means bail out to the regular compiler code below. |
| 2775 Object* result; | 2423 if (!code.is_null()) return code; |
| 2776 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 2777 // Undefined means bail out to regular compiler. | |
| 2778 if (!result->IsUndefined()) return result; | |
| 2779 } | 2424 } |
| 2780 | 2425 |
| 2781 Label miss; | 2426 Label miss; |
| 2782 | 2427 GenerateNameCheck(name, &miss); |
| 2783 GenerateNameCheck(Handle<String>(name), &miss); | |
| 2784 | 2428 |
| 2785 // Get the number of arguments. | 2429 // Get the number of arguments. |
| 2786 const int argc = arguments().immediate(); | 2430 const int argc = arguments().immediate(); |
| 2787 | |
| 2788 GenerateGlobalReceiverCheck(object, holder, name, &miss); | 2431 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 2789 GenerateLoadFunctionFromCell(cell, function, &miss); | 2432 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2790 | 2433 |
| 2791 // Patch the receiver on the stack with the global proxy if | 2434 // Patch the receiver on the stack with the global proxy if |
| 2792 // necessary. | 2435 // necessary. |
| 2793 if (object->IsGlobalObject()) { | 2436 if (object->IsGlobalObject()) { |
| 2794 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | 2437 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 2795 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | 2438 __ sw(a3, MemOperand(sp, argc * kPointerSize)); |
| 2796 } | 2439 } |
| 2797 | 2440 |
| 2798 // Setup the context (function already in r1). | 2441 // Setup the context (function already in r1). |
| 2799 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 2442 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 2800 | 2443 |
| 2801 // Jump to the cached code (tail call). | 2444 // Jump to the cached code (tail call). |
| 2802 Counters* counters = masm()->isolate()->counters(); | 2445 Counters* counters = masm()->isolate()->counters(); |
| 2803 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2446 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
| 2804 Handle<Code> code(function->code()); | |
| 2805 ParameterCount expected(function->shared()->formal_parameter_count()); | 2447 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2806 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2448 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) |
| 2807 ? CALL_AS_FUNCTION | 2449 ? CALL_AS_FUNCTION |
| 2808 : CALL_AS_METHOD; | 2450 : CALL_AS_METHOD; |
| 2809 // We call indirectly through the code field in the function to | 2451 // We call indirectly through the code field in the function to |
| 2810 // allow recompilation to take effect without changing any of the | 2452 // allow recompilation to take effect without changing any of the |
| 2811 // call sites. | 2453 // call sites. |
| 2812 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 2454 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 2813 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, | 2455 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, |
| 2814 NullCallWrapper(), call_kind); | 2456 NullCallWrapper(), call_kind); |
| 2815 | 2457 |
| 2816 // Handle call cache miss. | 2458 // Handle call cache miss. |
| 2817 __ bind(&miss); | 2459 __ bind(&miss); |
| 2818 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | 2460 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); |
| 2819 MaybeObject* maybe_result = TryGenerateMissBranch(); | 2461 GenerateMissBranch(); |
| 2820 if (maybe_result->IsFailure()) return maybe_result; | |
| 2821 | 2462 |
| 2822 // Return the generated code. | 2463 // Return the generated code. |
| 2823 return TryGetCode(NORMAL, name); | 2464 return GetCode(NORMAL, name); |
| 2824 } | 2465 } |
| 2825 | 2466 |
| 2826 | 2467 |
| 2827 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 2468 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, |
| 2828 int index, | 2469 int index, |
| 2829 Handle<Map> transition, | 2470 Handle<Map> transition, |
| 2830 Handle<String> name) { | 2471 Handle<String> name) { |
| 2831 // ----------- S t a t e ------------- | 2472 // ----------- S t a t e ------------- |
| 2832 // -- a0 : value | 2473 // -- a0 : value |
| 2833 // -- a1 : receiver | 2474 // -- a1 : receiver |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3046 | 2687 |
| 3047 GenerateLoadField(object, holder, v0, a3, a1, t0, index, name, &miss); | 2688 GenerateLoadField(object, holder, v0, a3, a1, t0, index, name, &miss); |
| 3048 __ bind(&miss); | 2689 __ bind(&miss); |
| 3049 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2690 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3050 | 2691 |
| 3051 // Return the generated code. | 2692 // Return the generated code. |
| 3052 return GetCode(FIELD, name); | 2693 return GetCode(FIELD, name); |
| 3053 } | 2694 } |
| 3054 | 2695 |
| 3055 | 2696 |
| 3056 MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, | 2697 Handle<Code> LoadStubCompiler::CompileLoadCallback( |
| 3057 JSObject* object, | 2698 Handle<String> name, |
| 3058 JSObject* holder, | 2699 Handle<JSObject> object, |
| 3059 AccessorInfo* callback) { | 2700 Handle<JSObject> holder, |
| 2701 Handle<AccessorInfo> callback) { |
| 3060 // ----------- S t a t e ------------- | 2702 // ----------- S t a t e ------------- |
| 3061 // -- a0 : receiver | 2703 // -- a0 : receiver |
| 3062 // -- a2 : name | 2704 // -- a2 : name |
| 3063 // -- ra : return address | 2705 // -- ra : return address |
| 3064 // ----------------------------------- | 2706 // ----------------------------------- |
| 3065 Label miss; | 2707 Label miss; |
| 3066 | 2708 GenerateLoadCallback(object, holder, a0, a2, a3, a1, t0, callback, name, |
| 3067 MaybeObject* result = GenerateLoadCallback(object, holder, a0, a2, a3, a1, t0, | 2709 &miss); |
| 3068 callback, name, &miss); | |
| 3069 if (result->IsFailure()) { | |
| 3070 miss.Unuse(); | |
| 3071 return result; | |
| 3072 } | |
| 3073 | |
| 3074 __ bind(&miss); | 2710 __ bind(&miss); |
| 3075 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2711 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3076 | 2712 |
| 3077 // Return the generated code. | 2713 // Return the generated code. |
| 3078 return TryGetCode(CALLBACKS, name); | 2714 return GetCode(CALLBACKS, name); |
| 3079 } | 2715 } |
| 3080 | 2716 |
| 3081 | 2717 |
| 3082 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, | 2718 Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, |
| 3083 Handle<JSObject> holder, | 2719 Handle<JSObject> holder, |
| 3084 Handle<Object> value, | 2720 Handle<Object> value, |
| 3085 Handle<String> name) { | 2721 Handle<String> name) { |
| 3086 // ----------- S t a t e ------------- | 2722 // ----------- S t a t e ------------- |
| 3087 // -- a0 : receiver | 2723 // -- a0 : receiver |
| 3088 // -- a2 : name | 2724 // -- a2 : name |
| 3089 // -- ra : return address | 2725 // -- ra : return address |
| 3090 // ----------------------------------- | 2726 // ----------------------------------- |
| 3091 Label miss; | 2727 Label miss; |
| 3092 | 2728 |
| 3093 GenerateLoadConstant(object, holder, a0, a3, a1, t0, value, name, &miss); | 2729 GenerateLoadConstant(object, holder, a0, a3, a1, t0, value, name, &miss); |
| 3094 __ bind(&miss); | 2730 __ bind(&miss); |
| 3095 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2731 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3096 | 2732 |
| 3097 // Return the generated code. | 2733 // Return the generated code. |
| 3098 return GetCode(CONSTANT_FUNCTION, name); | 2734 return GetCode(CONSTANT_FUNCTION, name); |
| 3099 } | 2735 } |
| 3100 | 2736 |
| 3101 | 2737 |
| 3102 MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, | 2738 Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, |
| 3103 JSObject* holder, | 2739 Handle<JSObject> holder, |
| 3104 String* name) { | 2740 Handle<String> name) { |
| 3105 // ----------- S t a t e ------------- | 2741 // ----------- S t a t e ------------- |
| 3106 // -- a0 : receiver | 2742 // -- a0 : receiver |
| 3107 // -- a2 : name | 2743 // -- a2 : name |
| 3108 // -- ra : return address | 2744 // -- ra : return address |
| 3109 // -- [sp] : receiver | 2745 // -- [sp] : receiver |
| 3110 // ----------------------------------- | 2746 // ----------------------------------- |
| 3111 Label miss; | 2747 Label miss; |
| 3112 | 2748 |
| 3113 LookupResult lookup(isolate()); | 2749 LookupResult lookup(isolate()); |
| 3114 LookupPostInterceptor(holder, name, &lookup); | 2750 LookupPostInterceptor(holder, name, &lookup); |
| 3115 GenerateLoadInterceptor(object, | 2751 GenerateLoadInterceptor(object, holder, &lookup, a0, a2, a3, a1, t0, name, |
| 3116 holder, | |
| 3117 &lookup, | |
| 3118 a0, | |
| 3119 a2, | |
| 3120 a3, | |
| 3121 a1, | |
| 3122 t0, | |
| 3123 name, | |
| 3124 &miss); | 2752 &miss); |
| 3125 __ bind(&miss); | 2753 __ bind(&miss); |
| 3126 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2754 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 3127 | 2755 |
| 3128 // Return the generated code. | 2756 // Return the generated code. |
| 3129 return TryGetCode(INTERCEPTOR, name); | 2757 return GetCode(INTERCEPTOR, name); |
| 3130 } | 2758 } |
| 3131 | 2759 |
| 3132 | 2760 |
| 3133 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2761 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 3134 Handle<JSObject> object, | 2762 Handle<JSObject> object, |
| 3135 Handle<GlobalObject> holder, | 2763 Handle<GlobalObject> holder, |
| 3136 Handle<JSGlobalPropertyCell> cell, | 2764 Handle<JSGlobalPropertyCell> cell, |
| 3137 Handle<String> name, | 2765 Handle<String> name, |
| 3138 bool is_dont_delete) { | 2766 bool is_dont_delete) { |
| 3139 // ----------- S t a t e ------------- | 2767 // ----------- S t a t e ------------- |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3193 __ Branch(&miss, ne, a0, Operand(name)); | 2821 __ Branch(&miss, ne, a0, Operand(name)); |
| 3194 | 2822 |
| 3195 GenerateLoadField(receiver, holder, a1, a2, a3, t0, index, name, &miss); | 2823 GenerateLoadField(receiver, holder, a1, a2, a3, t0, index, name, &miss); |
| 3196 __ bind(&miss); | 2824 __ bind(&miss); |
| 3197 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2825 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3198 | 2826 |
| 3199 return GetCode(FIELD, name); | 2827 return GetCode(FIELD, name); |
| 3200 } | 2828 } |
| 3201 | 2829 |
| 3202 | 2830 |
| 3203 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2831 Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback( |
| 3204 String* name, | 2832 Handle<String> name, |
| 3205 JSObject* receiver, | 2833 Handle<JSObject> receiver, |
| 3206 JSObject* holder, | 2834 Handle<JSObject> holder, |
| 3207 AccessorInfo* callback) { | 2835 Handle<AccessorInfo> callback) { |
| 3208 // ----------- S t a t e ------------- | 2836 // ----------- S t a t e ------------- |
| 3209 // -- ra : return address | 2837 // -- ra : return address |
| 3210 // -- a0 : key | 2838 // -- a0 : key |
| 3211 // -- a1 : receiver | 2839 // -- a1 : receiver |
| 3212 // ----------------------------------- | 2840 // ----------------------------------- |
| 3213 Label miss; | 2841 Label miss; |
| 3214 | 2842 |
| 3215 // Check the key is the cached one. | 2843 // Check the key is the cached one. |
| 3216 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 2844 __ Branch(&miss, ne, a0, Operand(name)); |
| 3217 | 2845 |
| 3218 MaybeObject* result = GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, | 2846 GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, t0, callback, name, |
| 3219 t0, callback, name, &miss); | 2847 &miss); |
| 3220 if (result->IsFailure()) { | |
| 3221 miss.Unuse(); | |
| 3222 return result; | |
| 3223 } | |
| 3224 | |
| 3225 __ bind(&miss); | 2848 __ bind(&miss); |
| 3226 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2849 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3227 | 2850 |
| 3228 return TryGetCode(CALLBACKS, name); | 2851 return GetCode(CALLBACKS, name); |
| 3229 } | 2852 } |
| 3230 | 2853 |
| 3231 | 2854 |
| 3232 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( | 2855 Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant( |
| 3233 Handle<String> name, | 2856 Handle<String> name, |
| 3234 Handle<JSObject> receiver, | 2857 Handle<JSObject> receiver, |
| 3235 Handle<JSObject> holder, | 2858 Handle<JSObject> holder, |
| 3236 Handle<Object> value) { | 2859 Handle<Object> value) { |
| 3237 // ----------- S t a t e ------------- | 2860 // ----------- S t a t e ------------- |
| 3238 // -- ra : return address | 2861 // -- ra : return address |
| 3239 // -- a0 : key | 2862 // -- a0 : key |
| 3240 // -- a1 : receiver | 2863 // -- a1 : receiver |
| 3241 // ----------------------------------- | 2864 // ----------------------------------- |
| 3242 Label miss; | 2865 Label miss; |
| 3243 | 2866 |
| 3244 // Check the key is the cached one. | 2867 // Check the key is the cached one. |
| 3245 __ Branch(&miss, ne, a0, Operand(name)); | 2868 __ Branch(&miss, ne, a0, Operand(name)); |
| 3246 | 2869 |
| 3247 GenerateLoadConstant(receiver, holder, a1, a2, a3, t0, value, name, &miss); | 2870 GenerateLoadConstant(receiver, holder, a1, a2, a3, t0, value, name, &miss); |
| 3248 __ bind(&miss); | 2871 __ bind(&miss); |
| 3249 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2872 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3250 | 2873 |
| 3251 // Return the generated code. | 2874 // Return the generated code. |
| 3252 return GetCode(CONSTANT_FUNCTION, name); | 2875 return GetCode(CONSTANT_FUNCTION, name); |
| 3253 } | 2876 } |
| 3254 | 2877 |
| 3255 | 2878 |
| 3256 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 2879 Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( |
| 3257 JSObject* holder, | 2880 Handle<JSObject> receiver, |
| 3258 String* name) { | 2881 Handle<JSObject> holder, |
| 2882 Handle<String> name) { |
| 3259 // ----------- S t a t e ------------- | 2883 // ----------- S t a t e ------------- |
| 3260 // -- ra : return address | 2884 // -- ra : return address |
| 3261 // -- a0 : key | 2885 // -- a0 : key |
| 3262 // -- a1 : receiver | 2886 // -- a1 : receiver |
| 3263 // ----------------------------------- | 2887 // ----------------------------------- |
| 3264 Label miss; | 2888 Label miss; |
| 3265 | 2889 |
| 3266 // Check the key is the cached one. | 2890 // Check the key is the cached one. |
| 3267 __ Branch(&miss, ne, a0, Operand(Handle<String>(name))); | 2891 __ Branch(&miss, ne, a0, Operand(name)); |
| 3268 | 2892 |
| 3269 LookupResult lookup(isolate()); | 2893 LookupResult lookup(isolate()); |
| 3270 LookupPostInterceptor(holder, name, &lookup); | 2894 LookupPostInterceptor(holder, name, &lookup); |
| 3271 GenerateLoadInterceptor(receiver, | 2895 GenerateLoadInterceptor(receiver, holder, &lookup, a1, a0, a2, a3, t0, name, |
| 3272 holder, | |
| 3273 &lookup, | |
| 3274 a1, | |
| 3275 a0, | |
| 3276 a2, | |
| 3277 a3, | |
| 3278 t0, | |
| 3279 name, | |
| 3280 &miss); | 2896 &miss); |
| 3281 __ bind(&miss); | 2897 __ bind(&miss); |
| 3282 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2898 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3283 | 2899 |
| 3284 return TryGetCode(INTERCEPTOR, name); | 2900 return GetCode(INTERCEPTOR, name); |
| 3285 } | 2901 } |
| 3286 | 2902 |
| 3287 | 2903 |
| 3288 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( | 2904 Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( |
| 3289 Handle<String> name) { | 2905 Handle<String> name) { |
| 3290 // ----------- S t a t e ------------- | 2906 // ----------- S t a t e ------------- |
| 3291 // -- ra : return address | 2907 // -- ra : return address |
| 3292 // -- a0 : key | 2908 // -- a0 : key |
| 3293 // -- a1 : receiver | 2909 // -- a1 : receiver |
| 3294 // ----------------------------------- | 2910 // ----------------------------------- |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3489 | 3105 |
| 3490 __ bind(&miss); | 3106 __ bind(&miss); |
| 3491 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3107 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3492 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 3108 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3493 | 3109 |
| 3494 // Return the generated code. | 3110 // Return the generated code. |
| 3495 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); | 3111 return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); |
| 3496 } | 3112 } |
| 3497 | 3113 |
| 3498 | 3114 |
| 3499 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3115 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
| 3116 Handle<JSFunction> function) { |
| 3500 // a0 : argc | 3117 // a0 : argc |
| 3501 // a1 : constructor | 3118 // a1 : constructor |
| 3502 // ra : return address | 3119 // ra : return address |
| 3503 // [sp] : last argument | 3120 // [sp] : last argument |
| 3504 Label generic_stub_call; | 3121 Label generic_stub_call; |
| 3505 | 3122 |
| 3506 // Use t7 for holding undefined which is used in several places below. | 3123 // Use t7 for holding undefined which is used in several places below. |
| 3507 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); | 3124 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); |
| 3508 | 3125 |
| 3509 #ifdef ENABLE_DEBUGGER_SUPPORT | 3126 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3534 __ Check(ne, "Function constructed by construct stub.", | 3151 __ Check(ne, "Function constructed by construct stub.", |
| 3535 a3, Operand(JS_FUNCTION_TYPE)); | 3152 a3, Operand(JS_FUNCTION_TYPE)); |
| 3536 #endif | 3153 #endif |
| 3537 | 3154 |
| 3538 // Now allocate the JSObject in new space. | 3155 // Now allocate the JSObject in new space. |
| 3539 // a0: argc | 3156 // a0: argc |
| 3540 // a1: constructor function | 3157 // a1: constructor function |
| 3541 // a2: initial map | 3158 // a2: initial map |
| 3542 // t7: undefined | 3159 // t7: undefined |
| 3543 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); | 3160 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); |
| 3544 __ AllocateInNewSpace(a3, | 3161 __ AllocateInNewSpace(a3, t4, t5, t6, &generic_stub_call, SIZE_IN_WORDS); |
| 3545 t4, | |
| 3546 t5, | |
| 3547 t6, | |
| 3548 &generic_stub_call, | |
| 3549 SIZE_IN_WORDS); | |
| 3550 | 3162 |
| 3551 // Allocated the JSObject, now initialize the fields. Map is set to initial | 3163 // Allocated the JSObject, now initialize the fields. Map is set to initial |
| 3552 // map and properties and elements are set to empty fixed array. | 3164 // map and properties and elements are set to empty fixed array. |
| 3553 // a0: argc | 3165 // a0: argc |
| 3554 // a1: constructor function | 3166 // a1: constructor function |
| 3555 // a2: initial map | 3167 // a2: initial map |
| 3556 // a3: object size (in words) | 3168 // a3: object size (in words) |
| 3557 // t4: JSObject (not tagged) | 3169 // t4: JSObject (not tagged) |
| 3558 // t7: undefined | 3170 // t7: undefined |
| 3559 __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); | 3171 __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3574 | 3186 |
| 3575 // Fill all the in-object properties with undefined. | 3187 // Fill all the in-object properties with undefined. |
| 3576 // a0: argc | 3188 // a0: argc |
| 3577 // a1: first argument | 3189 // a1: first argument |
| 3578 // a3: object size (in words) | 3190 // a3: object size (in words) |
| 3579 // t4: JSObject (not tagged) | 3191 // t4: JSObject (not tagged) |
| 3580 // t5: First in-object property of JSObject (not tagged) | 3192 // t5: First in-object property of JSObject (not tagged) |
| 3581 // t7: undefined | 3193 // t7: undefined |
| 3582 // Fill the initialized properties with a constant value or a passed argument | 3194 // Fill the initialized properties with a constant value or a passed argument |
| 3583 // depending on the this.x = ...; assignment in the function. | 3195 // depending on the this.x = ...; assignment in the function. |
| 3584 SharedFunctionInfo* shared = function->shared(); | 3196 Handle<SharedFunctionInfo> shared(function->shared()); |
| 3585 for (int i = 0; i < shared->this_property_assignments_count(); i++) { | 3197 for (int i = 0; i < shared->this_property_assignments_count(); i++) { |
| 3586 if (shared->IsThisPropertyAssignmentArgument(i)) { | 3198 if (shared->IsThisPropertyAssignmentArgument(i)) { |
| 3587 Label not_passed, next; | 3199 Label not_passed, next; |
| 3588 // Check if the argument assigned to the property is actually passed. | 3200 // Check if the argument assigned to the property is actually passed. |
| 3589 int arg_number = shared->GetThisPropertyAssignmentArgument(i); | 3201 int arg_number = shared->GetThisPropertyAssignmentArgument(i); |
| 3590 __ Branch(¬_passed, less_equal, a0, Operand(arg_number)); | 3202 __ Branch(¬_passed, less_equal, a0, Operand(arg_number)); |
| 3591 // Argument passed - find it on the stack. | 3203 // Argument passed - find it on the stack. |
| 3592 __ lw(a2, MemOperand(a1, (arg_number + 1) * -kPointerSize)); | 3204 __ lw(a2, MemOperand(a1, (arg_number + 1) * -kPointerSize)); |
| 3593 __ sw(a2, MemOperand(t5)); | 3205 __ sw(a2, MemOperand(t5)); |
| 3594 __ Addu(t5, t5, kPointerSize); | 3206 __ Addu(t5, t5, kPointerSize); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4046 // -- ra : return address | 3658 // -- ra : return address |
| 4047 // -- a0 : key | 3659 // -- a0 : key |
| 4048 // -- a1 : receiver | 3660 // -- a1 : receiver |
| 4049 // ----------------------------------- | 3661 // ----------------------------------- |
| 4050 | 3662 |
| 4051 __ Push(a1, a0); | 3663 __ Push(a1, a0); |
| 4052 | 3664 |
| 4053 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3665 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 4054 | 3666 |
| 4055 __ bind(&miss_force_generic); | 3667 __ bind(&miss_force_generic); |
| 4056 Code* stub = masm->isolate()->builtins()->builtin( | 3668 Handle<Code> stub = |
| 4057 Builtins::kKeyedLoadIC_MissForceGeneric); | 3669 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 4058 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 3670 __ Jump(stub, RelocInfo::CODE_TARGET); |
| 4059 } | 3671 } |
| 4060 | 3672 |
| 4061 | 3673 |
| 4062 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3674 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
| 4063 MacroAssembler* masm, | 3675 MacroAssembler* masm, |
| 4064 ElementsKind elements_kind) { | 3676 ElementsKind elements_kind) { |
| 4065 // ---------- S t a t e -------------- | 3677 // ---------- S t a t e -------------- |
| 4066 // -- a0 : value | 3678 // -- a0 : value |
| 4067 // -- a1 : key | 3679 // -- a1 : key |
| 4068 // -- a2 : receiver | 3680 // -- a2 : receiver |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4476 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 4088 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4477 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); | 4089 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); |
| 4478 __ Addu(t0, t0, a3); | 4090 __ Addu(t0, t0, a3); |
| 4479 __ lw(t0, MemOperand(t0)); | 4091 __ lw(t0, MemOperand(t0)); |
| 4480 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); | 4092 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); |
| 4481 __ Branch(&miss_force_generic, eq, t0, Operand(t1)); | 4093 __ Branch(&miss_force_generic, eq, t0, Operand(t1)); |
| 4482 __ mov(v0, t0); | 4094 __ mov(v0, t0); |
| 4483 __ Ret(); | 4095 __ Ret(); |
| 4484 | 4096 |
| 4485 __ bind(&miss_force_generic); | 4097 __ bind(&miss_force_generic); |
| 4486 Code* stub = masm->isolate()->builtins()->builtin( | 4098 Handle<Code> stub = |
| 4487 Builtins::kKeyedLoadIC_MissForceGeneric); | 4099 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 4488 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 4100 __ Jump(stub, RelocInfo::CODE_TARGET); |
| 4489 } | 4101 } |
| 4490 | 4102 |
| 4491 | 4103 |
| 4492 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( | 4104 void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( |
| 4493 MacroAssembler* masm) { | 4105 MacroAssembler* masm) { |
| 4494 // ----------- S t a t e ------------- | 4106 // ----------- S t a t e ------------- |
| 4495 // -- ra : return address | 4107 // -- ra : return address |
| 4496 // -- a0 : key | 4108 // -- a0 : key |
| 4497 // -- a1 : receiver | 4109 // -- a1 : receiver |
| 4498 // ----------------------------------- | 4110 // ----------------------------------- |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4711 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); | 4323 Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 4712 __ Jump(ic_miss, RelocInfo::CODE_TARGET); | 4324 __ Jump(ic_miss, RelocInfo::CODE_TARGET); |
| 4713 } | 4325 } |
| 4714 | 4326 |
| 4715 | 4327 |
| 4716 #undef __ | 4328 #undef __ |
| 4717 | 4329 |
| 4718 } } // namespace v8::internal | 4330 } } // namespace v8::internal |
| 4719 | 4331 |
| 4720 #endif // V8_TARGET_ARCH_MIPS | 4332 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |