| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 #include "src/v8.h" | 7 #include "src/v8.h" |
| 8 | 8 |
| 9 #if V8_TARGET_ARCH_MIPS | 9 #if V8_TARGET_ARCH_MIPS |
| 10 | 10 |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 __ bind(&unique); | 315 __ bind(&unique); |
| 316 } | 316 } |
| 317 | 317 |
| 318 | 318 |
| 319 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 319 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 320 // ----------- S t a t e ------------- | 320 // ----------- S t a t e ------------- |
| 321 // -- a2 : name | 321 // -- a2 : name |
| 322 // -- ra : return address | 322 // -- ra : return address |
| 323 // -- a0 : receiver | 323 // -- a0 : receiver |
| 324 // ----------------------------------- | 324 // ----------------------------------- |
| 325 ASSERT(a0.is(ReceiverRegister())); |
| 326 ASSERT(a2.is(NameRegister())); |
| 325 | 327 |
| 326 // Probe the stub cache. | 328 // Probe the stub cache. |
| 327 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 329 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 328 masm->isolate()->stub_cache()->GenerateProbe( | 330 masm->isolate()->stub_cache()->GenerateProbe( |
| 329 masm, flags, a0, a2, a3, t0, t1, t2); | 331 masm, flags, a0, a2, a3, t0, t1, t2); |
| 330 | 332 |
| 331 // Cache miss: Jump to runtime. | 333 // Cache miss: Jump to runtime. |
| 332 GenerateMiss(masm); | 334 GenerateMiss(masm); |
| 333 } | 335 } |
| 334 | 336 |
| 335 | 337 |
| 336 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 338 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 337 // ----------- S t a t e ------------- | 339 // ----------- S t a t e ------------- |
| 338 // -- a2 : name | 340 // -- a2 : name |
| 339 // -- lr : return address | 341 // -- lr : return address |
| 340 // -- a0 : receiver | 342 // -- a0 : receiver |
| 341 // ----------------------------------- | 343 // ----------------------------------- |
| 344 ASSERT(a0.is(ReceiverRegister())); |
| 345 ASSERT(a2.is(NameRegister())); |
| 346 |
| 342 Label miss, slow; | 347 Label miss, slow; |
| 343 | 348 |
| 344 GenerateNameDictionaryReceiverCheck(masm, a0, a1, a3, t0, &miss); | 349 GenerateNameDictionaryReceiverCheck(masm, a0, a1, a3, t0, &miss); |
| 345 | 350 |
| 346 // a1: elements | 351 // a1: elements |
| 347 GenerateDictionaryLoad(masm, &slow, a1, a2, v0, a3, t0); | 352 GenerateDictionaryLoad(masm, &slow, a1, a2, v0, a3, t0); |
| 348 __ Ret(); | 353 __ Ret(); |
| 349 | 354 |
| 350 // Dictionary load failed, go slow (but don't miss). | 355 // Dictionary load failed, go slow (but don't miss). |
| 351 __ bind(&slow); | 356 __ bind(&slow); |
| 352 GenerateRuntimeGetProperty(masm); | 357 GenerateRuntimeGetProperty(masm); |
| 353 | 358 |
| 354 // Cache miss: Jump to runtime. | 359 // Cache miss: Jump to runtime. |
| 355 __ bind(&miss); | 360 __ bind(&miss); |
| 356 GenerateMiss(masm); | 361 GenerateMiss(masm); |
| 357 } | 362 } |
| 358 | 363 |
| 359 | 364 |
| 365 // A register that isn't one of the parameters to the load ic. |
| 366 static const Register LoadIC_TempRegister() { return a3; } |
| 367 |
| 368 |
| 360 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 369 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 361 // ----------- S t a t e ------------- | 370 // The return address is on the stack. |
| 362 // -- a2 : name | |
| 363 // -- ra : return address | |
| 364 // -- a0 : receiver | |
| 365 // ----------------------------------- | |
| 366 Isolate* isolate = masm->isolate(); | 371 Isolate* isolate = masm->isolate(); |
| 367 | 372 |
| 368 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0); | 373 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0); |
| 369 | 374 |
| 370 __ mov(a3, a0); | 375 __ mov(LoadIC_TempRegister(), ReceiverRegister()); |
| 371 __ Push(a3, a2); | 376 __ Push(LoadIC_TempRegister(), NameRegister()); |
| 372 | 377 |
| 373 // Perform tail call to the entry. | 378 // Perform tail call to the entry. |
| 374 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); | 379 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); |
| 375 __ TailCallExternalReference(ref, 2, 1); | 380 __ TailCallExternalReference(ref, 2, 1); |
| 376 } | 381 } |
| 377 | 382 |
| 378 | 383 |
| 379 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 384 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 380 // ---------- S t a t e -------------- | 385 // The return address is on the stack. |
| 381 // -- a2 : name | |
| 382 // -- ra : return address | |
| 383 // -- a0 : receiver | |
| 384 // ----------------------------------- | |
| 385 | 386 |
| 386 __ mov(a3, a0); | 387 __ mov(LoadIC_TempRegister(), ReceiverRegister()); |
| 387 __ Push(a3, a2); | 388 __ Push(LoadIC_TempRegister(), NameRegister()); |
| 388 | 389 |
| 389 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); | 390 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); |
| 390 } | 391 } |
| 391 | 392 |
| 392 | 393 |
| 393 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, | 394 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
| 394 Register object, | 395 Register object, |
| 395 Register key, | 396 Register key, |
| 396 Register scratch1, | 397 Register scratch1, |
| 397 Register scratch2, | 398 Register scratch2, |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 return MemOperand(scratch); | 480 return MemOperand(scratch); |
| 480 } | 481 } |
| 481 | 482 |
| 482 | 483 |
| 483 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { | 484 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { |
| 484 // ---------- S t a t e -------------- | 485 // ---------- S t a t e -------------- |
| 485 // -- lr : return address | 486 // -- lr : return address |
| 486 // -- a0 : key | 487 // -- a0 : key |
| 487 // -- a1 : receiver | 488 // -- a1 : receiver |
| 488 // ----------------------------------- | 489 // ----------------------------------- |
| 490 ASSERT(a1.is(ReceiverRegister())); |
| 491 ASSERT(a0.is(NameRegister())); |
| 489 Label slow, notin; | 492 Label slow, notin; |
| 490 MemOperand mapped_location = | 493 MemOperand mapped_location = |
| 491 GenerateMappedArgumentsLookup(masm, a1, a0, a2, a3, t0, ¬in, &slow); | 494 GenerateMappedArgumentsLookup(masm, a1, a0, a2, a3, t0, ¬in, &slow); |
| 492 __ Ret(USE_DELAY_SLOT); | 495 __ Ret(USE_DELAY_SLOT); |
| 493 __ lw(v0, mapped_location); | 496 __ lw(v0, mapped_location); |
| 494 __ bind(¬in); | 497 __ bind(¬in); |
| 495 // The unmapped lookup expects that the parameter map is in a2. | 498 // The unmapped lookup expects that the parameter map is in a2. |
| 496 MemOperand unmapped_location = | 499 MemOperand unmapped_location = |
| 497 GenerateUnmappedArgumentsLookup(masm, a0, a2, a3, &slow); | 500 GenerateUnmappedArgumentsLookup(masm, a0, a2, a3, &slow); |
| 498 __ lw(a2, unmapped_location); | 501 __ lw(a2, unmapped_location); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 __ RecordWrite(a3, unmapped_location.rm(), t5, | 537 __ RecordWrite(a3, unmapped_location.rm(), t5, |
| 535 kRAHasNotBeenSaved, kDontSaveFPRegs); | 538 kRAHasNotBeenSaved, kDontSaveFPRegs); |
| 536 __ Ret(USE_DELAY_SLOT); | 539 __ Ret(USE_DELAY_SLOT); |
| 537 __ mov(v0, a0); // (In delay slot) return the value stored in v0. | 540 __ mov(v0, a0); // (In delay slot) return the value stored in v0. |
| 538 __ bind(&slow); | 541 __ bind(&slow); |
| 539 GenerateMiss(masm); | 542 GenerateMiss(masm); |
| 540 } | 543 } |
| 541 | 544 |
| 542 | 545 |
| 543 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | 546 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 544 // ---------- S t a t e -------------- | 547 // The return address is on the stack. |
| 545 // -- ra : return address | |
| 546 // -- a0 : key | |
| 547 // -- a1 : receiver | |
| 548 // ----------------------------------- | |
| 549 Isolate* isolate = masm->isolate(); | 548 Isolate* isolate = masm->isolate(); |
| 550 | 549 |
| 551 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0); | 550 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0); |
| 552 | 551 |
| 553 __ Push(a1, a0); | 552 __ Push(ReceiverRegister(), NameRegister()); |
| 554 | 553 |
| 555 // Perform tail call to the entry. | 554 // Perform tail call to the entry. |
| 556 ExternalReference ref = | 555 ExternalReference ref = |
| 557 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); | 556 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); |
| 558 | 557 |
| 559 __ TailCallExternalReference(ref, 2, 1); | 558 __ TailCallExternalReference(ref, 2, 1); |
| 560 } | 559 } |
| 561 | 560 |
| 562 | 561 |
| 563 // IC register specifications | 562 // IC register specifications |
| 564 const Register LoadIC::ReceiverRegister() { return a0; } | 563 const Register LoadIC::ReceiverRegister() { return a0; } |
| 565 const Register LoadIC::NameRegister() { return a2; } | 564 const Register LoadIC::NameRegister() { return a2; } |
| 566 const Register KeyedLoadIC::ReceiverRegister() { return a1; } | 565 const Register KeyedLoadIC::ReceiverRegister() { return a1; } |
| 567 const Register KeyedLoadIC::NameRegister() { return a0; } | 566 const Register KeyedLoadIC::NameRegister() { return a0; } |
| 568 | 567 |
| 569 | 568 |
| 570 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | 569 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 571 // ---------- S t a t e -------------- | 570 // The return address is on the stack. |
| 572 // -- ra : return address | |
| 573 // -- a0 : key | |
| 574 // -- a1 : receiver | |
| 575 // ----------------------------------- | |
| 576 | 571 |
| 577 __ Push(a1, a0); | 572 __ Push(ReceiverRegister(), NameRegister()); |
| 578 | 573 |
| 579 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 574 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 580 } | 575 } |
| 581 | 576 |
| 582 | 577 |
| 583 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 578 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 584 // ---------- S t a t e -------------- | 579 // ---------- S t a t e -------------- |
| 585 // -- ra : return address | 580 // -- ra : return address |
| 586 // -- a0 : key | 581 // -- a0 : key |
| 587 // -- a1 : receiver | 582 // -- a1 : receiver |
| 588 // ----------------------------------- | 583 // ----------------------------------- |
| 589 Label slow, check_name, index_smi, index_name, property_array_property; | 584 Label slow, check_name, index_smi, index_name, property_array_property; |
| 590 Label probe_dictionary, check_number_dictionary; | 585 Label probe_dictionary, check_number_dictionary; |
| 591 | 586 |
| 592 Register key = a0; | 587 Register key = NameRegister(); |
| 593 Register receiver = a1; | 588 Register receiver = ReceiverRegister(); |
| 589 ASSERT(key.is(a0)); |
| 590 ASSERT(receiver.is(a1)); |
| 594 | 591 |
| 595 Isolate* isolate = masm->isolate(); | 592 Isolate* isolate = masm->isolate(); |
| 596 | 593 |
| 597 // Check that the key is a smi. | 594 // Check that the key is a smi. |
| 598 __ JumpIfNotSmi(key, &check_name); | 595 __ JumpIfNotSmi(key, &check_name); |
| 599 __ bind(&index_smi); | 596 __ bind(&index_smi); |
| 600 // Now the key is known to be a smi. This place is also jumped to from below | 597 // Now the key is known to be a smi. This place is also jumped to from below |
| 601 // where a numeric string is converted to a smi. | 598 // where a numeric string is converted to a smi. |
| 602 | 599 |
| 603 GenerateKeyedLoadReceiverCheck( | 600 GenerateKeyedLoadReceiverCheck( |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 __ Ret(); | 749 __ Ret(); |
| 753 | 750 |
| 754 __ bind(&index_name); | 751 __ bind(&index_name); |
| 755 __ IndexFromHash(a3, key); | 752 __ IndexFromHash(a3, key); |
| 756 // Now jump to the place where smi keys are handled. | 753 // Now jump to the place where smi keys are handled. |
| 757 __ Branch(&index_smi); | 754 __ Branch(&index_smi); |
| 758 } | 755 } |
| 759 | 756 |
| 760 | 757 |
| 761 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 758 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
| 762 // ---------- S t a t e -------------- | 759 // Return address is on the stack. |
| 763 // -- ra : return address | |
| 764 // -- a0 : key (index) | |
| 765 // -- a1 : receiver | |
| 766 // ----------------------------------- | |
| 767 Label miss; | 760 Label miss; |
| 768 | 761 |
| 769 Register receiver = a1; | 762 Register receiver = ReceiverRegister(); |
| 770 Register index = a0; | 763 Register index = NameRegister(); |
| 771 Register scratch = a3; | 764 Register scratch = a3; |
| 772 Register result = v0; | 765 Register result = v0; |
| 766 ASSERT(!scratch.is(receiver) && !scratch.is(index)); |
| 773 | 767 |
| 774 StringCharAtGenerator char_at_generator(receiver, | 768 StringCharAtGenerator char_at_generator(receiver, |
| 775 index, | 769 index, |
| 776 scratch, | 770 scratch, |
| 777 result, | 771 result, |
| 778 &miss, // When not a string. | 772 &miss, // When not a string. |
| 779 &miss, // When not a number. | 773 &miss, // When not a number. |
| 780 &miss, // When index out of range. | 774 &miss, // When index out of range. |
| 781 STRING_INDEX_IS_ARRAY_INDEX); | 775 STRING_INDEX_IS_ARRAY_INDEX); |
| 782 char_at_generator.GenerateFast(masm); | 776 char_at_generator.GenerateFast(masm); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 value, key, receiver, receiver_map, | 1065 value, key, receiver, receiver_map, |
| 1072 elements_map, elements); | 1066 elements_map, elements); |
| 1073 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, | 1067 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, |
| 1074 &slow, kDontCheckMap, kIncrementLength, | 1068 &slow, kDontCheckMap, kIncrementLength, |
| 1075 value, key, receiver, receiver_map, | 1069 value, key, receiver, receiver_map, |
| 1076 elements_map, elements); | 1070 elements_map, elements); |
| 1077 } | 1071 } |
| 1078 | 1072 |
| 1079 | 1073 |
| 1080 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 1074 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 1081 // ---------- S t a t e -------------- | 1075 // Return address is on the stack. |
| 1082 // -- ra : return address | |
| 1083 // -- a0 : key | |
| 1084 // -- a1 : receiver | |
| 1085 // ----------------------------------- | |
| 1086 Label slow; | 1076 Label slow; |
| 1087 | 1077 |
| 1078 Register receiver = ReceiverRegister(); |
| 1079 Register key = NameRegister(); |
| 1080 Register scratch1 = a2; |
| 1081 Register scratch2 = a3; |
| 1082 ASSERT(!scratch1.is(receiver) && !scratch1.is(key)); |
| 1083 ASSERT(!scratch2.is(receiver) && !scratch2.is(key)); |
| 1084 |
| 1088 // Check that the receiver isn't a smi. | 1085 // Check that the receiver isn't a smi. |
| 1089 __ JumpIfSmi(a1, &slow); | 1086 __ JumpIfSmi(receiver, &slow); |
| 1090 | 1087 |
| 1091 // Check that the key is an array index, that is Uint32. | 1088 // Check that the key is an array index, that is Uint32. |
| 1092 __ And(t0, a0, Operand(kSmiTagMask | kSmiSignMask)); | 1089 __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask)); |
| 1093 __ Branch(&slow, ne, t0, Operand(zero_reg)); | 1090 __ Branch(&slow, ne, t0, Operand(zero_reg)); |
| 1094 | 1091 |
| 1095 // Get the map of the receiver. | 1092 // Get the map of the receiver. |
| 1096 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); | 1093 __ lw(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1097 | 1094 |
| 1098 // Check that it has indexed interceptor and access checks | 1095 // Check that it has indexed interceptor and access checks |
| 1099 // are not enabled for this object. | 1096 // are not enabled for this object. |
| 1100 __ lbu(a3, FieldMemOperand(a2, Map::kBitFieldOffset)); | 1097 __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset)); |
| 1101 __ And(a3, a3, Operand(kSlowCaseBitFieldMask)); | 1098 __ And(scratch2, scratch2, Operand(kSlowCaseBitFieldMask)); |
| 1102 __ Branch(&slow, ne, a3, Operand(1 << Map::kHasIndexedInterceptor)); | 1099 __ Branch(&slow, ne, scratch2, Operand(1 << Map::kHasIndexedInterceptor)); |
| 1103 // Everything is fine, call runtime. | 1100 // Everything is fine, call runtime. |
| 1104 __ Push(a1, a0); // Receiver, key. | 1101 __ Push(receiver, key); // Receiver, key. |
| 1105 | 1102 |
| 1106 // Perform tail call to the entry. | 1103 // Perform tail call to the entry. |
| 1107 __ TailCallExternalReference(ExternalReference( | 1104 __ TailCallExternalReference(ExternalReference( |
| 1108 IC_Utility(kKeyedLoadPropertyWithInterceptor), masm->isolate()), 2, 1); | 1105 IC_Utility(kKeyedLoadPropertyWithInterceptor), masm->isolate()), 2, 1); |
| 1109 | 1106 |
| 1110 __ bind(&slow); | 1107 __ bind(&slow); |
| 1111 GenerateMiss(masm); | 1108 GenerateMiss(masm); |
| 1112 } | 1109 } |
| 1113 | 1110 |
| 1114 | 1111 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1338 } else { | 1335 } else { |
| 1339 ASSERT(Assembler::IsBne(branch_instr)); | 1336 ASSERT(Assembler::IsBne(branch_instr)); |
| 1340 patcher.ChangeBranchCondition(eq); | 1337 patcher.ChangeBranchCondition(eq); |
| 1341 } | 1338 } |
| 1342 } | 1339 } |
| 1343 | 1340 |
| 1344 | 1341 |
| 1345 } } // namespace v8::internal | 1342 } } // namespace v8::internal |
| 1346 | 1343 |
| 1347 #endif // V8_TARGET_ARCH_MIPS | 1344 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |