| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 __ movq(dst, FieldOperand(src, offset)); | 126 __ movq(dst, FieldOperand(src, offset)); |
| 127 } else { | 127 } else { |
| 128 // Calculate the offset into the properties array. | 128 // Calculate the offset into the properties array. |
| 129 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 129 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
| 130 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | 130 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| 131 __ movq(dst, FieldOperand(dst, offset)); | 131 __ movq(dst, FieldOperand(dst, offset)); |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 | 134 |
| 135 | 135 |
| 136 template <typename Pushable> | |
| 137 static void PushInterceptorArguments(MacroAssembler* masm, | 136 static void PushInterceptorArguments(MacroAssembler* masm, |
| 138 Register receiver, | 137 Register receiver, |
| 139 Register holder, | 138 Register holder, |
| 140 Pushable name, | 139 Register name, |
| 141 JSObject* holder_obj) { | 140 JSObject* holder_obj) { |
| 142 __ push(receiver); | 141 __ push(receiver); |
| 143 __ push(holder); | 142 __ push(holder); |
| 144 __ push(name); | 143 __ push(name); |
| 145 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 144 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
| 146 ASSERT(!Heap::InNewSpace(interceptor)); | 145 ASSERT(!Heap::InNewSpace(interceptor)); |
| 147 __ movq(kScratchRegister, Handle<Object>(interceptor), | 146 __ movq(kScratchRegister, Handle<Object>(interceptor), |
| 148 RelocInfo::EMBEDDED_OBJECT); | 147 RelocInfo::EMBEDDED_OBJECT); |
| 149 __ push(kScratchRegister); | 148 __ push(kScratchRegister); |
| 150 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); | 149 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 | 193 |
| 195 // Probe the secondary table. | 194 // Probe the secondary table. |
| 196 ProbeTable(masm, flags, kSecondary, name, scratch); | 195 ProbeTable(masm, flags, kSecondary, name, scratch); |
| 197 | 196 |
| 198 // Cache miss: Fall-through and let caller handle the miss by | 197 // Cache miss: Fall-through and let caller handle the miss by |
| 199 // entering the runtime system. | 198 // entering the runtime system. |
| 200 __ bind(&miss); | 199 __ bind(&miss); |
| 201 } | 200 } |
| 202 | 201 |
| 203 | 202 |
| 203 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
| 204 // but may be destroyed if store is successful. |
| 204 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 205 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
| 205 Builtins::Name storage_extend, | |
| 206 JSObject* object, | 206 JSObject* object, |
| 207 int index, | 207 int index, |
| 208 Map* transition, | 208 Map* transition, |
| 209 Register receiver_reg, | 209 Register receiver_reg, |
| 210 Register name_reg, | 210 Register name_reg, |
| 211 Register scratch, | 211 Register scratch, |
| 212 Label* miss_label) { | 212 Label* miss_label) { |
| 213 // Check that the object isn't a smi. | 213 // Check that the object isn't a smi. |
| 214 __ JumpIfSmi(receiver_reg, miss_label); | 214 __ JumpIfSmi(receiver_reg, miss_label); |
| 215 | 215 |
| 216 // Check that the map of the object hasn't changed. | 216 // Check that the map of the object hasn't changed. |
| 217 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 217 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 218 Handle<Map>(object->map())); | 218 Handle<Map>(object->map())); |
| 219 __ j(not_equal, miss_label); | 219 __ j(not_equal, miss_label); |
| 220 | 220 |
| 221 // Perform global security token check if needed. | 221 // Perform global security token check if needed. |
| 222 if (object->IsJSGlobalProxy()) { | 222 if (object->IsJSGlobalProxy()) { |
| 223 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); | 223 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); |
| 224 } | 224 } |
| 225 | 225 |
| 226 // Stub never generated for non-global objects that require access | 226 // Stub never generated for non-global objects that require access |
| 227 // checks. | 227 // checks. |
| 228 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 228 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 229 | 229 |
| 230 // Perform map transition for the receiver if necessary. | 230 // Perform map transition for the receiver if necessary. |
| 231 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { | 231 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { |
| 232 // The properties must be extended before we can store the value. | 232 // The properties must be extended before we can store the value. |
| 233 // We jump to a runtime call that extends the properties array. | 233 // We jump to a runtime call that extends the properties array. |
| 234 __ Move(rcx, Handle<Map>(transition)); | 234 __ pop(scratch); // Return address. |
| 235 Handle<Code> ic(Builtins::builtin(storage_extend)); | 235 __ push(receiver_reg); |
| 236 __ Jump(ic, RelocInfo::CODE_TARGET); | 236 __ Push(Handle<Map>(transition)); |
| 237 __ push(rax); |
| 238 __ push(scratch); |
| 239 __ TailCallRuntime( |
| 240 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage)), 3, 1); |
| 237 return; | 241 return; |
| 238 } | 242 } |
| 239 | 243 |
| 240 if (transition != NULL) { | 244 if (transition != NULL) { |
| 241 // Update the map of the object; no write barrier updating is | 245 // Update the map of the object; no write barrier updating is |
| 242 // needed because the map is never in new space. | 246 // needed because the map is never in new space. |
| 243 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), | 247 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), |
| 244 Handle<Map>(transition)); | 248 Handle<Map>(transition)); |
| 245 } | 249 } |
| 246 | 250 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); | 311 __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 308 __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); | 312 __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); |
| 309 ASSERT(kNotStringTag != 0); | 313 ASSERT(kNotStringTag != 0); |
| 310 __ testl(scratch, Immediate(kNotStringTag)); | 314 __ testl(scratch, Immediate(kNotStringTag)); |
| 311 __ j(not_zero, non_string_object); | 315 __ j(not_zero, non_string_object); |
| 312 } | 316 } |
| 313 | 317 |
| 314 | 318 |
| 315 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, | 319 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, |
| 316 Register receiver, | 320 Register receiver, |
| 317 Register scratch, | 321 Register scratch1, |
| 322 Register scratch2, |
| 318 Label* miss) { | 323 Label* miss) { |
| 319 Label load_length, check_wrapper; | 324 Label check_wrapper; |
| 320 | 325 |
| 321 // Check if the object is a string leaving the instance type in the | 326 // Check if the object is a string leaving the instance type in the |
| 322 // scratch register. | 327 // scratch register. |
| 323 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper); | 328 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); |
| 324 | 329 |
| 325 // Load length directly from the string. | 330 // Load length directly from the string. |
| 326 __ bind(&load_length); | |
| 327 __ movl(rax, FieldOperand(receiver, String::kLengthOffset)); | 331 __ movl(rax, FieldOperand(receiver, String::kLengthOffset)); |
| 328 __ Integer32ToSmi(rax, rax); | 332 __ Integer32ToSmi(rax, rax); |
| 329 __ ret(0); | 333 __ ret(0); |
| 330 | 334 |
| 331 // Check if the object is a JSValue wrapper. | 335 // Check if the object is a JSValue wrapper. |
| 332 __ bind(&check_wrapper); | 336 __ bind(&check_wrapper); |
| 333 __ cmpl(scratch, Immediate(JS_VALUE_TYPE)); | 337 __ cmpl(scratch1, Immediate(JS_VALUE_TYPE)); |
| 334 __ j(not_equal, miss); | 338 __ j(not_equal, miss); |
| 335 | 339 |
| 336 // Check if the wrapped value is a string and load the length | 340 // Check if the wrapped value is a string and load the length |
| 337 // directly if it is. | 341 // directly if it is. |
| 338 __ movq(receiver, FieldOperand(receiver, JSValue::kValueOffset)); | 342 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); |
| 339 GenerateStringCheck(masm, receiver, scratch, miss, miss); | 343 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); |
| 340 __ jmp(&load_length); | 344 __ movl(rax, FieldOperand(scratch2, String::kLengthOffset)); |
| 345 __ Integer32ToSmi(rax, rax); |
| 346 __ ret(0); |
| 341 } | 347 } |
| 342 | 348 |
| 343 | 349 |
| 344 template <class Pushable> | |
| 345 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, | 350 static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm, |
| 346 Register receiver, | 351 Register receiver, |
| 347 Register holder, | 352 Register holder, |
| 348 Pushable name, | 353 Register name, |
| 349 JSObject* holder_obj) { | 354 JSObject* holder_obj) { |
| 350 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 355 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
| 351 | 356 |
| 352 ExternalReference ref = | 357 ExternalReference ref = |
| 353 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 358 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
| 354 __ movq(rax, Immediate(5)); | 359 __ movq(rax, Immediate(5)); |
| 355 __ movq(rbx, ref); | 360 __ movq(rbx, ref); |
| 356 | 361 |
| 357 CEntryStub stub(1); | 362 CEntryStub stub(1); |
| 358 __ CallStub(&stub); | 363 __ CallStub(&stub); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 387 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 392 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 388 | 393 |
| 389 // Check that the receiver isn't a smi. | 394 // Check that the receiver isn't a smi. |
| 390 __ JumpIfSmi(receiver, miss); | 395 __ JumpIfSmi(receiver, miss); |
| 391 | 396 |
| 392 // Check that the maps haven't changed. | 397 // Check that the maps haven't changed. |
| 393 Register reg = | 398 Register reg = |
| 394 stub_compiler->CheckPrototypes(object, receiver, holder, | 399 stub_compiler->CheckPrototypes(object, receiver, holder, |
| 395 scratch1, scratch2, name, miss); | 400 scratch1, scratch2, name, miss); |
| 396 | 401 |
| 397 if (lookup->IsValid() && lookup->IsCacheable()) { | 402 if (lookup->IsProperty() && lookup->IsCacheable()) { |
| 398 compiler->CompileCacheable(masm, | 403 compiler->CompileCacheable(masm, |
| 399 stub_compiler, | 404 stub_compiler, |
| 400 receiver, | 405 receiver, |
| 401 reg, | 406 reg, |
| 402 scratch1, | 407 scratch1, |
| 403 scratch2, | 408 scratch2, |
| 404 holder, | 409 holder, |
| 405 lookup, | 410 lookup, |
| 406 name, | 411 name, |
| 407 miss); | 412 miss); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 423 void CompileCacheable(MacroAssembler* masm, | 428 void CompileCacheable(MacroAssembler* masm, |
| 424 StubCompiler* stub_compiler, | 429 StubCompiler* stub_compiler, |
| 425 Register receiver, | 430 Register receiver, |
| 426 Register holder, | 431 Register holder, |
| 427 Register scratch1, | 432 Register scratch1, |
| 428 Register scratch2, | 433 Register scratch2, |
| 429 JSObject* holder_obj, | 434 JSObject* holder_obj, |
| 430 LookupResult* lookup, | 435 LookupResult* lookup, |
| 431 String* name, | 436 String* name, |
| 432 Label* miss_label) { | 437 Label* miss_label) { |
| 433 AccessorInfo* callback = 0; | 438 AccessorInfo* callback = NULL; |
| 434 bool optimize = false; | 439 bool optimize = false; |
| 435 // So far the most popular follow ups for interceptor loads are FIELD | 440 // So far the most popular follow ups for interceptor loads are FIELD |
| 436 // and CALLBACKS, so inline only them, other cases may be added | 441 // and CALLBACKS, so inline only them, other cases may be added |
| 437 // later. | 442 // later. |
| 438 if (lookup->type() == FIELD) { | 443 if (lookup->type() == FIELD) { |
| 439 optimize = true; | 444 optimize = true; |
| 440 } else if (lookup->type() == CALLBACKS) { | 445 } else if (lookup->type() == CALLBACKS) { |
| 441 Object* callback_object = lookup->GetCallbackObject(); | 446 Object* callback_object = lookup->GetCallbackObject(); |
| 442 if (callback_object->IsAccessorInfo()) { | 447 if (callback_object->IsAccessorInfo()) { |
| 443 callback = AccessorInfo::cast(callback_object); | 448 callback = AccessorInfo::cast(callback_object); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 __ TailCallRuntime(ref, 5, 1); | 551 __ TailCallRuntime(ref, 5, 1); |
| 547 } | 552 } |
| 548 | 553 |
| 549 private: | 554 private: |
| 550 Register name_; | 555 Register name_; |
| 551 }; | 556 }; |
| 552 | 557 |
| 553 | 558 |
| 554 class CallInterceptorCompiler BASE_EMBEDDED { | 559 class CallInterceptorCompiler BASE_EMBEDDED { |
| 555 public: | 560 public: |
| 556 explicit CallInterceptorCompiler(const ParameterCount& arguments) | 561 CallInterceptorCompiler(const ParameterCount& arguments, Register name) |
| 557 : arguments_(arguments), argc_(arguments.immediate()) {} | 562 : arguments_(arguments), name_(name) {} |
| 558 | 563 |
| 559 void CompileCacheable(MacroAssembler* masm, | 564 void CompileCacheable(MacroAssembler* masm, |
| 560 StubCompiler* stub_compiler, | 565 StubCompiler* stub_compiler, |
| 561 Register receiver, | 566 Register receiver, |
| 562 Register holder, | 567 Register holder, |
| 563 Register scratch1, | 568 Register scratch1, |
| 564 Register scratch2, | 569 Register scratch2, |
| 565 JSObject* holder_obj, | 570 JSObject* holder_obj, |
| 566 LookupResult* lookup, | 571 LookupResult* lookup, |
| 567 String* name, | 572 String* name, |
| 568 Label* miss_label) { | 573 Label* miss_label) { |
| 569 JSFunction* function = 0; | 574 JSFunction* function = 0; |
| 570 bool optimize = false; | 575 bool optimize = false; |
| 571 // So far the most popular case for failed interceptor is | 576 // So far the most popular case for failed interceptor is |
| 572 // CONSTANT_FUNCTION sitting below. | 577 // CONSTANT_FUNCTION sitting below. |
| 573 if (lookup->type() == CONSTANT_FUNCTION) { | 578 if (lookup->type() == CONSTANT_FUNCTION) { |
| 574 function = lookup->GetConstantFunction(); | 579 function = lookup->GetConstantFunction(); |
| 575 // JSArray holder is a special case for call constant function | 580 // JSArray holder is a special case for call constant function |
| 576 // (see the corresponding code). | 581 // (see the corresponding code). |
| 577 if (function->is_compiled() && !holder_obj->IsJSArray()) { | 582 if (function->is_compiled() && !holder_obj->IsJSArray()) { |
| 578 optimize = true; | 583 optimize = true; |
| 579 } | 584 } |
| 580 } | 585 } |
| 581 | 586 |
| 582 if (!optimize) { | 587 if (!optimize) { |
| 583 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); | 588 CompileRegular(masm, receiver, holder, scratch2, holder_obj, miss_label); |
| 584 return; | 589 return; |
| 585 } | 590 } |
| 586 | 591 |
| 592 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 593 |
| 587 __ EnterInternalFrame(); | 594 __ EnterInternalFrame(); |
| 588 __ push(holder); // save the holder | 595 __ push(holder); // Save the holder. |
| 596 __ push(name_); // Save the name. |
| 589 | 597 |
| 590 CompileCallLoadPropertyWithInterceptor( | 598 CompileCallLoadPropertyWithInterceptor(masm, |
| 591 masm, | 599 receiver, |
| 592 receiver, | 600 holder, |
| 593 holder, | 601 name_, |
| 594 // Under EnterInternalFrame this refers to name. | 602 holder_obj); |
| 595 Operand(rbp, (argc_ + 3) * kPointerSize), | |
| 596 holder_obj); | |
| 597 | 603 |
| 598 __ pop(receiver); // restore holder | 604 __ pop(name_); // Restore the name. |
| 605 __ pop(receiver); // Restore the holder. |
| 599 __ LeaveInternalFrame(); | 606 __ LeaveInternalFrame(); |
| 600 | 607 |
| 601 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 608 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 602 Label invoke; | 609 Label invoke; |
| 603 __ j(not_equal, &invoke); | 610 __ j(not_equal, &invoke); |
| 604 | 611 |
| 605 stub_compiler->CheckPrototypes(holder_obj, receiver, | 612 stub_compiler->CheckPrototypes(holder_obj, receiver, |
| 606 lookup->holder(), scratch1, | 613 lookup->holder(), scratch1, |
| 607 scratch2, | 614 scratch2, |
| 608 name, | 615 name, |
| 609 miss_label); | 616 miss_label); |
| 610 if (lookup->holder()->IsGlobalObject()) { | |
| 611 __ movq(rdx, Operand(rsp, (argc_ + 1) * kPointerSize)); | |
| 612 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
| 613 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdx); | |
| 614 } | |
| 615 | 617 |
| 616 ASSERT(function->is_compiled()); | 618 __ InvokeFunction(function, arguments_, JUMP_FUNCTION); |
| 617 // Get the function and setup the context. | |
| 618 __ Move(rdi, Handle<JSFunction>(function)); | |
| 619 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
| 620 | |
| 621 // Jump to the cached code (tail call). | |
| 622 Handle<Code> code(function->code()); | |
| 623 ParameterCount expected(function->shared()->formal_parameter_count()); | |
| 624 __ InvokeCode(code, expected, arguments_, | |
| 625 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
| 626 | 619 |
| 627 __ bind(&invoke); | 620 __ bind(&invoke); |
| 628 } | 621 } |
| 629 | 622 |
| 630 void CompileRegular(MacroAssembler* masm, | 623 void CompileRegular(MacroAssembler* masm, |
| 631 Register receiver, | 624 Register receiver, |
| 632 Register holder, | 625 Register holder, |
| 633 Register scratch, | 626 Register scratch, |
| 634 JSObject* holder_obj, | 627 JSObject* holder_obj, |
| 635 Label* miss_label) { | 628 Label* miss_label) { |
| 636 __ EnterInternalFrame(); | 629 __ EnterInternalFrame(); |
| 630 // Save the name_ register across the call. |
| 631 __ push(name_); |
| 637 | 632 |
| 638 PushInterceptorArguments(masm, | 633 PushInterceptorArguments(masm, |
| 639 receiver, | 634 receiver, |
| 640 holder, | 635 holder, |
| 641 Operand(rbp, (argc_ + 3) * kPointerSize), | 636 name_, |
| 642 holder_obj); | 637 holder_obj); |
| 643 | 638 |
| 644 ExternalReference ref = ExternalReference( | 639 __ CallExternalReference( |
| 645 IC_Utility(IC::kLoadPropertyWithInterceptorForCall)); | 640 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall)), |
| 646 __ movq(rax, Immediate(5)); | 641 5); |
| 647 __ movq(rbx, ref); | |
| 648 | 642 |
| 649 CEntryStub stub(1); | 643 __ pop(name_); |
| 650 __ CallStub(&stub); | |
| 651 | |
| 652 __ LeaveInternalFrame(); | 644 __ LeaveInternalFrame(); |
| 653 } | 645 } |
| 654 | 646 |
| 655 private: | 647 private: |
| 656 const ParameterCount& arguments_; | 648 const ParameterCount& arguments_; |
| 657 int argc_; | 649 Register name_; |
| 658 }; | 650 }; |
| 659 | 651 |
| 660 | 652 |
| 661 #undef __ | 653 #undef __ |
| 662 | 654 |
| 663 #define __ ACCESS_MASM((masm())) | 655 #define __ ACCESS_MASM((masm())) |
| 664 | 656 |
| 665 | 657 |
| 666 Object* CallStubCompiler::CompileCallConstant(Object* object, | 658 Object* CallStubCompiler::CompileCallConstant(Object* object, |
| 667 JSObject* holder, | 659 JSObject* holder, |
| 668 JSFunction* function, | 660 JSFunction* function, |
| 669 String* name, | 661 String* name, |
| 670 StubCompiler::CheckType check) { | 662 StubCompiler::CheckType check) { |
| 671 // ----------- S t a t e ------------- | 663 // ----------- S t a t e ------------- |
| 664 // rcx : function name |
| 665 // rsp[0] : return address |
| 666 // rsp[8] : argument argc |
| 667 // rsp[16] : argument argc - 1 |
| 668 // ... |
| 669 // rsp[argc * 8] : argument 1 |
| 670 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 672 // ----------------------------------- | 671 // ----------------------------------- |
| 673 // rsp[0] return address | |
| 674 // rsp[8] argument argc | |
| 675 // rsp[16] argument argc - 1 | |
| 676 // ... | |
| 677 // rsp[argc * 8] argument 1 | |
| 678 // rsp[(argc + 1) * 8] argument 0 = receiver | |
| 679 // rsp[(argc + 2) * 8] function name | |
| 680 | 672 |
| 681 Label miss; | 673 Label miss; |
| 682 | 674 |
| 683 // Get the receiver from the stack. | 675 // Get the receiver from the stack. |
| 684 const int argc = arguments().immediate(); | 676 const int argc = arguments().immediate(); |
| 685 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 677 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 686 | 678 |
| 687 // Check that the receiver isn't a smi. | 679 // Check that the receiver isn't a smi. |
| 688 if (check != NUMBER_CHECK) { | 680 if (check != NUMBER_CHECK) { |
| 689 __ JumpIfSmi(rdx, &miss); | 681 __ JumpIfSmi(rdx, &miss); |
| 690 } | 682 } |
| 691 | 683 |
| 692 // Make sure that it's okay not to patch the on stack receiver | 684 // Make sure that it's okay not to patch the on stack receiver |
| 693 // unless we're doing a receiver map check. | 685 // unless we're doing a receiver map check. |
| 694 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 686 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 695 | 687 |
| 696 switch (check) { | 688 switch (check) { |
| 697 case RECEIVER_MAP_CHECK: | 689 case RECEIVER_MAP_CHECK: |
| 698 // Check that the maps haven't changed. | 690 // Check that the maps haven't changed. |
| 699 CheckPrototypes(JSObject::cast(object), rdx, holder, | 691 CheckPrototypes(JSObject::cast(object), rdx, holder, |
| 700 rbx, rcx, name, &miss); | 692 rbx, rax, name, &miss); |
| 701 | 693 |
| 702 // Patch the receiver on the stack with the global proxy if | 694 // Patch the receiver on the stack with the global proxy if |
| 703 // necessary. | 695 // necessary. |
| 704 if (object->IsGlobalObject()) { | 696 if (object->IsGlobalObject()) { |
| 705 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 697 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 706 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 698 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 707 } | 699 } |
| 708 break; | 700 break; |
| 709 | 701 |
| 710 case STRING_CHECK: | 702 case STRING_CHECK: |
| 711 if (!function->IsBuiltin()) { | 703 if (!function->IsBuiltin()) { |
| 712 // Calling non-builtins with a value as receiver requires boxing. | 704 // Calling non-builtins with a value as receiver requires boxing. |
| 713 __ jmp(&miss); | 705 __ jmp(&miss); |
| 714 } else { | 706 } else { |
| 715 // Check that the object is a two-byte string or a symbol. | 707 // Check that the object is a two-byte string or a symbol. |
| 716 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rcx); | 708 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); |
| 717 __ j(above_equal, &miss); | 709 __ j(above_equal, &miss); |
| 718 // Check that the maps starting from the prototype haven't changed. | 710 // Check that the maps starting from the prototype haven't changed. |
| 719 GenerateLoadGlobalFunctionPrototype(masm(), | 711 GenerateLoadGlobalFunctionPrototype(masm(), |
| 720 Context::STRING_FUNCTION_INDEX, | 712 Context::STRING_FUNCTION_INDEX, |
| 721 rcx); | 713 rax); |
| 722 CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, | 714 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 723 rbx, rdx, name, &miss); | 715 rbx, rdx, name, &miss); |
| 724 } | 716 } |
| 725 break; | 717 break; |
| 726 | 718 |
| 727 case NUMBER_CHECK: { | 719 case NUMBER_CHECK: { |
| 728 if (!function->IsBuiltin()) { | 720 if (!function->IsBuiltin()) { |
| 729 // Calling non-builtins with a value as receiver requires boxing. | 721 // Calling non-builtins with a value as receiver requires boxing. |
| 730 __ jmp(&miss); | 722 __ jmp(&miss); |
| 731 } else { | 723 } else { |
| 732 Label fast; | 724 Label fast; |
| 733 // Check that the object is a smi or a heap number. | 725 // Check that the object is a smi or a heap number. |
| 734 __ JumpIfSmi(rdx, &fast); | 726 __ JumpIfSmi(rdx, &fast); |
| 735 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rcx); | 727 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); |
| 736 __ j(not_equal, &miss); | 728 __ j(not_equal, &miss); |
| 737 __ bind(&fast); | 729 __ bind(&fast); |
| 738 // Check that the maps starting from the prototype haven't changed. | 730 // Check that the maps starting from the prototype haven't changed. |
| 739 GenerateLoadGlobalFunctionPrototype(masm(), | 731 GenerateLoadGlobalFunctionPrototype(masm(), |
| 740 Context::NUMBER_FUNCTION_INDEX, | 732 Context::NUMBER_FUNCTION_INDEX, |
| 741 rcx); | 733 rax); |
| 742 CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, | 734 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 743 rbx, rdx, name, &miss); | 735 rbx, rdx, name, &miss); |
| 744 } | 736 } |
| 745 break; | 737 break; |
| 746 } | 738 } |
| 747 | 739 |
| 748 case BOOLEAN_CHECK: { | 740 case BOOLEAN_CHECK: { |
| 749 if (!function->IsBuiltin()) { | 741 if (!function->IsBuiltin()) { |
| 750 // Calling non-builtins with a value as receiver requires boxing. | 742 // Calling non-builtins with a value as receiver requires boxing. |
| 751 __ jmp(&miss); | 743 __ jmp(&miss); |
| 752 } else { | 744 } else { |
| 753 Label fast; | 745 Label fast; |
| 754 // Check that the object is a boolean. | 746 // Check that the object is a boolean. |
| 755 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); | 747 __ CompareRoot(rdx, Heap::kTrueValueRootIndex); |
| 756 __ j(equal, &fast); | 748 __ j(equal, &fast); |
| 757 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); | 749 __ CompareRoot(rdx, Heap::kFalseValueRootIndex); |
| 758 __ j(not_equal, &miss); | 750 __ j(not_equal, &miss); |
| 759 __ bind(&fast); | 751 __ bind(&fast); |
| 760 // Check that the maps starting from the prototype haven't changed. | 752 // Check that the maps starting from the prototype haven't changed. |
| 761 GenerateLoadGlobalFunctionPrototype(masm(), | 753 GenerateLoadGlobalFunctionPrototype(masm(), |
| 762 Context::BOOLEAN_FUNCTION_INDEX, | 754 Context::BOOLEAN_FUNCTION_INDEX, |
| 763 rcx); | 755 rax); |
| 764 CheckPrototypes(JSObject::cast(object->GetPrototype()), rcx, holder, | 756 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 765 rbx, rdx, name, &miss); | 757 rbx, rdx, name, &miss); |
| 766 } | 758 } |
| 767 break; | 759 break; |
| 768 } | 760 } |
| 769 | 761 |
| 770 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: | 762 case JSARRAY_HAS_FAST_ELEMENTS_CHECK: |
| 771 CheckPrototypes(JSObject::cast(object), rdx, holder, | 763 CheckPrototypes(JSObject::cast(object), rdx, holder, |
| 772 rbx, rcx, name, &miss); | 764 rbx, rax, name, &miss); |
| 773 // Make sure object->HasFastElements(). | 765 // Make sure object->HasFastElements(). |
| 774 // Get the elements array of the object. | 766 // Get the elements array of the object. |
| 775 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 767 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 776 // Check that the object is in fast mode (not dictionary). | 768 // Check that the object is in fast mode (not dictionary). |
| 777 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), | 769 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), |
| 778 Factory::fixed_array_map()); | 770 Factory::fixed_array_map()); |
| 779 __ j(not_equal, &miss); | 771 __ j(not_equal, &miss); |
| 780 break; | 772 break; |
| 781 | 773 |
| 782 default: | 774 default: |
| 783 UNREACHABLE(); | 775 UNREACHABLE(); |
| 784 } | 776 } |
| 785 | 777 |
| 786 // Get the function and setup the context. | 778 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 787 __ Move(rdi, Handle<JSFunction>(function)); | |
| 788 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | |
| 789 | |
| 790 // Jump to the cached code (tail call). | |
| 791 ASSERT(function->is_compiled()); | |
| 792 Handle<Code> code(function->code()); | |
| 793 ParameterCount expected(function->shared()->formal_parameter_count()); | |
| 794 __ InvokeCode(code, expected, arguments(), | |
| 795 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | |
| 796 | 779 |
| 797 // Handle call cache miss. | 780 // Handle call cache miss. |
| 798 __ bind(&miss); | 781 __ bind(&miss); |
| 799 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 782 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
| 800 __ Jump(ic, RelocInfo::CODE_TARGET); | 783 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 801 | 784 |
| 802 // Return the generated code. | 785 // Return the generated code. |
| 803 String* function_name = NULL; | 786 String* function_name = NULL; |
| 804 if (function->shared()->name()->IsString()) { | 787 if (function->shared()->name()->IsString()) { |
| 805 function_name = String::cast(function->shared()->name()); | 788 function_name = String::cast(function->shared()->name()); |
| 806 } | 789 } |
| 807 return GetCode(CONSTANT_FUNCTION, function_name); | 790 return GetCode(CONSTANT_FUNCTION, function_name); |
| 808 } | 791 } |
| 809 | 792 |
| 810 | 793 |
| 811 Object* CallStubCompiler::CompileCallField(Object* object, | 794 Object* CallStubCompiler::CompileCallField(JSObject* object, |
| 812 JSObject* holder, | 795 JSObject* holder, |
| 813 int index, | 796 int index, |
| 814 String* name) { | 797 String* name) { |
| 815 // ----------- S t a t e ------------- | 798 // ----------- S t a t e ------------- |
| 799 // rcx : function name |
| 800 // rsp[0] : return address |
| 801 // rsp[8] : argument argc |
| 802 // rsp[16] : argument argc - 1 |
| 803 // ... |
| 804 // rsp[argc * 8] : argument 1 |
| 805 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 816 // ----------------------------------- | 806 // ----------------------------------- |
| 817 // rsp[0] return address | |
| 818 // rsp[8] argument argc | |
| 819 // rsp[16] argument argc - 1 | |
| 820 // ... | |
| 821 // rsp[argc * 8] argument 1 | |
| 822 // rsp[(argc + 1) * 8] argument 0 = receiver | |
| 823 // rsp[(argc + 2) * 8] function name | |
| 824 Label miss; | 807 Label miss; |
| 825 | 808 |
| 826 // Get the receiver from the stack. | 809 // Get the receiver from the stack. |
| 827 const int argc = arguments().immediate(); | 810 const int argc = arguments().immediate(); |
| 828 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 811 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 829 | 812 |
| 830 // Check that the receiver isn't a smi. | 813 // Check that the receiver isn't a smi. |
| 831 __ JumpIfSmi(rdx, &miss); | 814 __ JumpIfSmi(rdx, &miss); |
| 832 | 815 |
| 833 // Do the right check and compute the holder register. | 816 // Do the right check and compute the holder register. |
| 834 Register reg = | 817 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, name, &miss); |
| 835 CheckPrototypes(JSObject::cast(object), rdx, holder, | |
| 836 rbx, rcx, name, &miss); | |
| 837 | 818 |
| 838 GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); | 819 GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); |
| 839 | 820 |
| 840 // Check that the function really is a function. | 821 // Check that the function really is a function. |
| 841 __ JumpIfSmi(rdi, &miss); | 822 __ JumpIfSmi(rdi, &miss); |
| 842 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | 823 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
| 843 __ j(not_equal, &miss); | 824 __ j(not_equal, &miss); |
| 844 | 825 |
| 845 // Patch the receiver on the stack with the global proxy if | 826 // Patch the receiver on the stack with the global proxy if |
| 846 // necessary. | 827 // necessary. |
| 847 if (object->IsGlobalObject()) { | 828 if (object->IsGlobalObject()) { |
| 848 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 829 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 849 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 830 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 850 } | 831 } |
| 851 | 832 |
| 852 // Invoke the function. | 833 // Invoke the function. |
| 853 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION); | 834 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION); |
| 854 | 835 |
| 855 // Handle call cache miss. | 836 // Handle call cache miss. |
| 856 __ bind(&miss); | 837 __ bind(&miss); |
| 857 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); | 838 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); |
| 858 __ Jump(ic, RelocInfo::CODE_TARGET); | 839 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 859 | 840 |
| 860 // Return the generated code. | 841 // Return the generated code. |
| 861 return GetCode(FIELD, name); | 842 return GetCode(FIELD, name); |
| 862 } | 843 } |
| 863 | 844 |
| 864 | 845 |
| 865 Object* CallStubCompiler::CompileCallInterceptor(Object* object, | 846 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 866 JSObject* holder, | 847 JSObject* holder, |
| 867 String* name) { | 848 String* name) { |
| 868 // ----------- S t a t e ------------- | 849 // ----------- S t a t e ------------- |
| 850 // rcx : function name |
| 851 // rsp[0] : return address |
| 852 // rsp[8] : argument argc |
| 853 // rsp[16] : argument argc - 1 |
| 854 // ... |
| 855 // rsp[argc * 8] : argument 1 |
| 856 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 869 // ----------------------------------- | 857 // ----------------------------------- |
| 870 Label miss; | 858 Label miss; |
| 871 | 859 |
| 872 // Get the number of arguments. | 860 // Get the number of arguments. |
| 873 const int argc = arguments().immediate(); | 861 const int argc = arguments().immediate(); |
| 874 | 862 |
| 875 LookupResult lookup; | 863 LookupResult lookup; |
| 876 LookupPostInterceptor(holder, name, &lookup); | 864 LookupPostInterceptor(holder, name, &lookup); |
| 877 | 865 |
| 878 // Get the receiver from the stack. | 866 // Get the receiver from the stack. |
| 879 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 867 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 880 | 868 |
| 881 CallInterceptorCompiler compiler(arguments()); | 869 CallInterceptorCompiler compiler(arguments(), rcx); |
| 882 CompileLoadInterceptor(&compiler, | 870 CompileLoadInterceptor(&compiler, |
| 883 this, | 871 this, |
| 884 masm(), | 872 masm(), |
| 885 JSObject::cast(object), | 873 object, |
| 886 holder, | 874 holder, |
| 887 name, | 875 name, |
| 888 &lookup, | 876 &lookup, |
| 889 rdx, | 877 rdx, |
| 890 rbx, | 878 rbx, |
| 891 rcx, | 879 rdi, |
| 892 &miss); | 880 &miss); |
| 893 | 881 |
| 894 // Restore receiver. | 882 // Restore receiver. |
| 895 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 883 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 896 | 884 |
| 897 // Check that the function really is a function. | 885 // Check that the function really is a function. |
| 898 __ JumpIfSmi(rax, &miss); | 886 __ JumpIfSmi(rax, &miss); |
| 899 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 887 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 900 __ j(not_equal, &miss); | 888 __ j(not_equal, &miss); |
| 901 | 889 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 913 // Handle load cache miss. | 901 // Handle load cache miss. |
| 914 __ bind(&miss); | 902 __ bind(&miss); |
| 915 Handle<Code> ic = ComputeCallMiss(argc); | 903 Handle<Code> ic = ComputeCallMiss(argc); |
| 916 __ Jump(ic, RelocInfo::CODE_TARGET); | 904 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 917 | 905 |
| 918 // Return the generated code. | 906 // Return the generated code. |
| 919 return GetCode(INTERCEPTOR, name); | 907 return GetCode(INTERCEPTOR, name); |
| 920 } | 908 } |
| 921 | 909 |
| 922 | 910 |
| 923 | |
| 924 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, | 911 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 925 GlobalObject* holder, | 912 GlobalObject* holder, |
| 926 JSGlobalPropertyCell* cell, | 913 JSGlobalPropertyCell* cell, |
| 927 JSFunction* function, | 914 JSFunction* function, |
| 928 String* name) { | 915 String* name) { |
| 929 // ----------- S t a t e ------------- | 916 // ----------- S t a t e ------------- |
| 930 // ----------------------------------- | 917 // ----------------------------------- |
| 931 // rsp[0] return address | 918 // rcx : function name |
| 932 // rsp[8] argument argc | 919 // rsp[0] : return address |
| 933 // rsp[16] argument argc - 1 | 920 // rsp[8] : argument argc |
| 921 // rsp[16] : argument argc - 1 |
| 934 // ... | 922 // ... |
| 935 // rsp[argc * 8] argument 1 | 923 // rsp[argc * 8] : argument 1 |
| 936 // rsp[(argc + 1) * 8] argument 0 = receiver | 924 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 937 // rsp[(argc + 2) * 8] function name | |
| 938 Label miss; | 925 Label miss; |
| 939 | 926 |
| 940 // Get the number of arguments. | 927 // Get the number of arguments. |
| 941 const int argc = arguments().immediate(); | 928 const int argc = arguments().immediate(); |
| 942 | 929 |
| 943 // Get the receiver from the stack. | 930 // Get the receiver from the stack. |
| 944 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 931 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 945 | 932 |
| 946 // If the object is the holder then we know that it's a global | 933 // If the object is the holder then we know that it's a global |
| 947 // object which can only happen for contextual calls. In this case, | 934 // object which can only happen for contextual calls. In this case, |
| 948 // the receiver cannot be a smi. | 935 // the receiver cannot be a smi. |
| 949 if (object != holder) { | 936 if (object != holder) { |
| 950 __ JumpIfSmi(rdx, &miss); | 937 __ JumpIfSmi(rdx, &miss); |
| 951 } | 938 } |
| 952 | 939 |
| 953 // Check that the maps haven't changed. | 940 // Check that the maps haven't changed. |
| 954 CheckPrototypes(object, rdx, holder, rbx, rcx, name, &miss); | 941 CheckPrototypes(object, rdx, holder, rbx, rax, name, &miss); |
| 955 | 942 |
| 956 // Get the value from the cell. | 943 // Get the value from the cell. |
| 957 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); | 944 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); |
| 958 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); | 945 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); |
| 959 | 946 |
| 960 // Check that the cell contains the same function. | 947 // Check that the cell contains the same function. |
| 961 if (Heap::InNewSpace(function)) { | 948 if (Heap::InNewSpace(function)) { |
| 962 // We can't embed a pointer to a function in new space so we have | 949 // We can't embed a pointer to a function in new space so we have |
| 963 // to verify that the shared function info is unchanged. This has | 950 // to verify that the shared function info is unchanged. This has |
| 964 // the nice side effect that multiple closures based on the same | 951 // the nice side effect that multiple closures based on the same |
| 965 // function can all use this call IC. Before we load through the | 952 // function can all use this call IC. Before we load through the |
| 966 // function, we have to verify that it still is a function. | 953 // function, we have to verify that it still is a function. |
| 967 __ JumpIfSmi(rdi, &miss); | 954 __ JumpIfSmi(rdi, &miss); |
| 968 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | 955 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); |
| 969 __ j(not_equal, &miss); | 956 __ j(not_equal, &miss); |
| 970 | 957 |
| 971 // Check the shared function info. Make sure it hasn't changed. | 958 // Check the shared function info. Make sure it hasn't changed. |
| 972 __ Move(rcx, Handle<SharedFunctionInfo>(function->shared())); | 959 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); |
| 973 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rcx); | 960 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); |
| 974 __ j(not_equal, &miss); | 961 __ j(not_equal, &miss); |
| 975 } else { | 962 } else { |
| 976 __ Cmp(rdi, Handle<JSFunction>(function)); | 963 __ Cmp(rdi, Handle<JSFunction>(function)); |
| 977 __ j(not_equal, &miss); | 964 __ j(not_equal, &miss); |
| 978 } | 965 } |
| 979 | 966 |
| 980 // Patch the receiver on the stack with the global proxy. | 967 // Patch the receiver on the stack with the global proxy. |
| 981 if (object->IsGlobalObject()) { | 968 if (object->IsGlobalObject()) { |
| 982 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 969 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 983 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 970 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 Label miss; | 1305 Label miss; |
| 1319 | 1306 |
| 1320 __ movq(rax, Operand(rsp, kPointerSize)); | 1307 __ movq(rax, Operand(rsp, kPointerSize)); |
| 1321 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); | 1308 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); |
| 1322 __ IncrementCounter(&Counters::keyed_load_string_length, 1); | 1309 __ IncrementCounter(&Counters::keyed_load_string_length, 1); |
| 1323 | 1310 |
| 1324 // Check that the name has not changed. | 1311 // Check that the name has not changed. |
| 1325 __ Cmp(rax, Handle<String>(name)); | 1312 __ Cmp(rax, Handle<String>(name)); |
| 1326 __ j(not_equal, &miss); | 1313 __ j(not_equal, &miss); |
| 1327 | 1314 |
| 1328 GenerateLoadStringLength(masm(), rcx, rdx, &miss); | 1315 GenerateLoadStringLength(masm(), rcx, rdx, rbx, &miss); |
| 1329 __ bind(&miss); | 1316 __ bind(&miss); |
| 1330 __ DecrementCounter(&Counters::keyed_load_string_length, 1); | 1317 __ DecrementCounter(&Counters::keyed_load_string_length, 1); |
| 1331 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 1318 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 1332 | 1319 |
| 1333 // Return the generated code. | 1320 // Return the generated code. |
| 1334 return GetCode(CALLBACKS, name); | 1321 return GetCode(CALLBACKS, name); |
| 1335 } | 1322 } |
| 1336 | 1323 |
| 1337 | 1324 |
| 1338 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 1325 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 Map* transition, | 1377 Map* transition, |
| 1391 String* name) { | 1378 String* name) { |
| 1392 // ----------- S t a t e ------------- | 1379 // ----------- S t a t e ------------- |
| 1393 // -- rax : value | 1380 // -- rax : value |
| 1394 // -- rcx : name | 1381 // -- rcx : name |
| 1395 // -- rdx : receiver | 1382 // -- rdx : receiver |
| 1396 // -- rsp[0] : return address | 1383 // -- rsp[0] : return address |
| 1397 // ----------------------------------- | 1384 // ----------------------------------- |
| 1398 Label miss; | 1385 Label miss; |
| 1399 | 1386 |
| 1400 // Generate store field code. Trashes the name register. | 1387 // Generate store field code. Preserves receiver and name on jump to miss. |
| 1401 GenerateStoreField(masm(), | 1388 GenerateStoreField(masm(), |
| 1402 Builtins::StoreIC_ExtendStorage, | |
| 1403 object, | 1389 object, |
| 1404 index, | 1390 index, |
| 1405 transition, | 1391 transition, |
| 1406 rdx, rcx, rbx, | 1392 rdx, rcx, rbx, |
| 1407 &miss); | 1393 &miss); |
| 1408 | 1394 |
| 1409 // Handle store cache miss. | 1395 // Handle store cache miss. |
| 1410 __ bind(&miss); | 1396 __ bind(&miss); |
| 1411 __ Move(rcx, Handle<String>(name)); // restore name | |
| 1412 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); | 1397 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); |
| 1413 __ Jump(ic, RelocInfo::CODE_TARGET); | 1398 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 1414 | 1399 |
| 1415 // Return the generated code. | 1400 // Return the generated code. |
| 1416 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 1401 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 1417 } | 1402 } |
| 1418 | 1403 |
| 1419 | 1404 |
| 1420 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 1405 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, |
| 1421 String* name) { | 1406 String* name) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1543 Label miss; | 1528 Label miss; |
| 1544 | 1529 |
| 1545 __ IncrementCounter(&Counters::keyed_store_field, 1); | 1530 __ IncrementCounter(&Counters::keyed_store_field, 1); |
| 1546 | 1531 |
| 1547 // Get the name from the stack. | 1532 // Get the name from the stack. |
| 1548 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 1533 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| 1549 // Check that the name has not changed. | 1534 // Check that the name has not changed. |
| 1550 __ Cmp(rcx, Handle<String>(name)); | 1535 __ Cmp(rcx, Handle<String>(name)); |
| 1551 __ j(not_equal, &miss); | 1536 __ j(not_equal, &miss); |
| 1552 | 1537 |
| 1553 // Get the object from the stack. | 1538 // Get the receiver from the stack. |
| 1554 __ movq(rbx, Operand(rsp, 2 * kPointerSize)); | 1539 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 1555 | 1540 |
| 1556 // Generate store field code. Trashes the name register. | 1541 // Generate store field code. Preserves receiver and name on jump to miss. |
| 1557 GenerateStoreField(masm(), | 1542 GenerateStoreField(masm(), |
| 1558 Builtins::KeyedStoreIC_ExtendStorage, | |
| 1559 object, | 1543 object, |
| 1560 index, | 1544 index, |
| 1561 transition, | 1545 transition, |
| 1562 rbx, rcx, rdx, | 1546 rdx, rcx, rbx, |
| 1563 &miss); | 1547 &miss); |
| 1564 | 1548 |
| 1565 // Handle store cache miss. | 1549 // Handle store cache miss. |
| 1566 __ bind(&miss); | 1550 __ bind(&miss); |
| 1567 __ DecrementCounter(&Counters::keyed_store_field, 1); | 1551 __ DecrementCounter(&Counters::keyed_store_field, 1); |
| 1568 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | 1552 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); |
| 1569 __ Jump(ic, RelocInfo::CODE_TARGET); | 1553 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 1570 | 1554 |
| 1571 // Return the generated code. | 1555 // Return the generated code. |
| 1572 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 1556 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1658 return true; | 1642 return true; |
| 1659 } | 1643 } |
| 1660 | 1644 |
| 1661 | 1645 |
| 1662 Register StubCompiler::CheckPrototypes(JSObject* object, | 1646 Register StubCompiler::CheckPrototypes(JSObject* object, |
| 1663 Register object_reg, | 1647 Register object_reg, |
| 1664 JSObject* holder, | 1648 JSObject* holder, |
| 1665 Register holder_reg, | 1649 Register holder_reg, |
| 1666 Register scratch, | 1650 Register scratch, |
| 1667 String* name, | 1651 String* name, |
| 1652 int save_at_depth, |
| 1668 Label* miss) { | 1653 Label* miss) { |
| 1654 // TODO(602): support object saving. |
| 1655 ASSERT(save_at_depth == kInvalidProtoDepth); |
| 1656 |
| 1669 // Check that the maps haven't changed. | 1657 // Check that the maps haven't changed. |
| 1670 Register result = | 1658 Register result = |
| 1671 __ CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); | 1659 __ CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); |
| 1672 | 1660 |
| 1673 // If we've skipped any global objects, it's not enough to verify | 1661 // If we've skipped any global objects, it's not enough to verify |
| 1674 // that their maps haven't changed. | 1662 // that their maps haven't changed. |
| 1675 while (object != holder) { | 1663 while (object != holder) { |
| 1676 if (object->IsGlobalObject()) { | 1664 if (object->IsGlobalObject()) { |
| 1677 GlobalObject* global = GlobalObject::cast(object); | 1665 GlobalObject* global = GlobalObject::cast(object); |
| 1678 Object* probe = global->EnsurePropertyCell(name); | 1666 Object* probe = global->EnsurePropertyCell(name); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1865 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 1853 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 1866 | 1854 |
| 1867 // Return the generated code. | 1855 // Return the generated code. |
| 1868 return GetCode(); | 1856 return GetCode(); |
| 1869 } | 1857 } |
| 1870 | 1858 |
| 1871 | 1859 |
| 1872 #undef __ | 1860 #undef __ |
| 1873 | 1861 |
| 1874 } } // namespace v8::internal | 1862 } } // namespace v8::internal |
| OLD | NEW |