OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 // When lazily generated invocation dispatchers are disabled, the | 532 // When lazily generated invocation dispatchers are disabled, the |
533 // miss-handler may return null. | 533 // miss-handler may return null. |
534 __ CompareObject(R0, Object::null_object()); | 534 __ CompareObject(R0, Object::null_object()); |
535 __ b(call_target_function, NE); | 535 __ b(call_target_function, NE); |
536 __ EnterStubFrame(); | 536 __ EnterStubFrame(); |
537 // Load the receiver. | 537 // Load the receiver. |
538 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 538 __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
539 __ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi. | 539 __ add(IP, FP, Operand(R2, LSL, 1)); // R2 is Smi. |
540 __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize)); | 540 __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize)); |
541 __ PushObject(Object::null_object()); | 541 __ PushObject(Object::null_object()); |
542 __ Push(R8); | 542 __ Push(R8); // Receiver. |
543 __ Push(R9); | 543 __ Push(R9); // ICData/MegamorphicCache. |
544 __ Push(R4); | 544 __ Push(R4); // Arguments descriptor. |
545 // R2: Smi-tagged arguments array length. | 545 // R2: Smi-tagged arguments array length. |
546 PushArgumentsArray(assembler); | 546 PushArgumentsArray(assembler); |
547 const intptr_t kNumArgs = 4; | 547 const intptr_t kNumArgs = 4; |
548 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); | 548 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); |
549 __ Drop(4); | 549 __ Drop(4); |
550 __ Pop(R0); // Return value. | 550 __ Pop(R0); // Return value. |
551 __ LeaveStubFrame(); | 551 __ LeaveStubFrame(); |
552 __ Ret(); | 552 __ Ret(); |
553 } | 553 } |
554 | 554 |
(...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2037 const Register temp = R2; | 2037 const Register temp = R2; |
2038 const Register left = R1; | 2038 const Register left = R1; |
2039 const Register right = R0; | 2039 const Register right = R0; |
2040 __ ldr(left, Address(SP, 1 * kWordSize)); | 2040 __ ldr(left, Address(SP, 1 * kWordSize)); |
2041 __ ldr(right, Address(SP, 0 * kWordSize)); | 2041 __ ldr(right, Address(SP, 0 * kWordSize)); |
2042 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2042 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
2043 __ Ret(); | 2043 __ Ret(); |
2044 } | 2044 } |
2045 | 2045 |
2046 | 2046 |
2047 void StubCode::EmitMegamorphicLookup( | 2047 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
2048 Assembler* assembler, Register receiver, Register cache, Register target) { | 2048 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
2049 ASSERT((cache != R0) && (cache != R2)); | 2049 // R0: receiver cid as Smi. |
2050 __ LoadTaggedClassIdMayBeSmi(R0, receiver); | 2050 __ ldr(R4, FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset())); |
2051 // R0: class ID of the receiver (smi). | 2051 __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset())); |
2052 __ ldr(R2, FieldAddress(cache, MegamorphicCache::buckets_offset())); | 2052 __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset())); |
2053 __ ldr(R1, FieldAddress(R1, MegamorphicCache::mask_offset())); | |
2054 // R2: cache buckets array. | 2053 // R2: cache buckets array. |
2055 // R1: mask. | 2054 // R1: mask. |
2056 __ mov(R3, Operand(R0)); | 2055 __ mov(R3, Operand(R0)); |
| 2056 // R3: probe. |
2057 | 2057 |
2058 Label loop, update, call_target_function; | 2058 Label loop, update, load_target_function; |
2059 __ b(&loop); | 2059 __ b(&loop); |
2060 | 2060 |
2061 __ Bind(&update); | 2061 __ Bind(&update); |
2062 __ add(R3, R3, Operand(Smi::RawValue(1))); | 2062 __ add(R3, R3, Operand(Smi::RawValue(1))); |
2063 __ Bind(&loop); | 2063 __ Bind(&loop); |
2064 __ and_(R3, R3, Operand(R1)); | 2064 __ and_(R3, R3, Operand(R1)); |
2065 const intptr_t base = Array::data_offset(); | 2065 const intptr_t base = Array::data_offset(); |
2066 // R3 is smi tagged, but table entries are two words, so LSL 2. | 2066 // R3 is smi tagged, but table entries are two words, so LSL 2. |
2067 __ add(IP, R2, Operand(R3, LSL, 2)); | 2067 __ add(IP, R2, Operand(R3, LSL, 2)); |
2068 __ ldr(R4, FieldAddress(IP, base)); | 2068 __ ldr(R6, FieldAddress(IP, base)); |
2069 | 2069 |
2070 ASSERT(kIllegalCid == 0); | 2070 ASSERT(kIllegalCid == 0); |
2071 __ tst(R4, Operand(R4)); | 2071 __ tst(R6, Operand(R6)); |
2072 __ b(&call_target_function, EQ); | 2072 __ b(&load_target_function, EQ); |
2073 __ cmp(R4, Operand(R0)); | 2073 __ cmp(R6, Operand(R0)); |
2074 __ b(&update, NE); | 2074 __ b(&update, NE); |
2075 | 2075 |
2076 __ Bind(&call_target_function); | 2076 __ Bind(&load_target_function); |
2077 // Call the target found in the cache. For a class id match, this is a | 2077 // Call the target found in the cache. For a class id match, this is a |
2078 // proper target for the given name and arguments descriptor. If the | 2078 // proper target for the given name and arguments descriptor. If the |
2079 // illegal class id was found, the target is a cache miss handler that can | 2079 // illegal class id was found, the target is a cache miss handler that can |
2080 // be invoked as a normal Dart function. | 2080 // be invoked as a normal Dart function. |
2081 __ add(IP, R2, Operand(R3, LSL, 2)); | 2081 __ add(IP, R2, Operand(R3, LSL, 2)); |
2082 __ ldr(R0, FieldAddress(IP, base + kWordSize)); | 2082 __ ldr(R0, FieldAddress(IP, base + kWordSize)); |
| 2083 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2083 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2084 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2084 __ ldr(target, FieldAddress(R0, Function::entry_point_offset())); | |
2085 } | 2085 } |
2086 | 2086 |
2087 | 2087 |
2088 // Called from megamorphic calls. | 2088 // Called from megamorphic calls. |
2089 // R0: receiver. | 2089 // R0: receiver |
2090 // R1: lookup cache. | 2090 // R9: MegamorphicCache (preserved) |
2091 // Result: | 2091 // Result: |
2092 // R1: entry point. | 2092 // R1: target entry point |
| 2093 // CODE_REG: target Code |
| 2094 // R4: arguments descriptor |
2093 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2095 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2094 EmitMegamorphicLookup(assembler, R0, R1, R1); | 2096 EmitMegamorphicLookup(assembler); |
2095 __ Ret(); | 2097 __ Ret(); |
2096 } | 2098 } |
2097 | 2099 |
| 2100 |
| 2101 // Called from switchable IC calls. |
| 2102 // R0: receiver |
| 2103 // R9: ICData (preserved) |
| 2104 // Result: |
| 2105 // R1: target entry point |
| 2106 // CODE_REG: target Code object |
| 2107 // R4: arguments descriptor |
| 2108 void StubCode::GenerateICLookupStub(Assembler* assembler) { |
| 2109 Label loop, found, miss; |
| 2110 __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset())); |
| 2111 __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset())); |
| 2112 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); |
| 2113 // R8: first IC entry |
| 2114 __ LoadTaggedClassIdMayBeSmi(R1, R0); |
| 2115 // R1: receiver cid as Smi |
| 2116 |
| 2117 __ Bind(&loop); |
| 2118 __ ldr(R2, Address(R8, 0)); |
| 2119 __ cmp(R1, Operand(R2)); |
| 2120 __ b(&found, EQ); |
| 2121 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
| 2122 __ b(&miss, EQ); |
| 2123 |
| 2124 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
| 2125 __ AddImmediate(R8, entry_length); // Next entry. |
| 2126 __ b(&loop); |
| 2127 |
| 2128 __ Bind(&found); |
| 2129 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; |
| 2130 __ LoadFromOffset(kWord, R0, R8, target_offset); |
| 2131 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
| 2132 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
| 2133 __ Ret(); |
| 2134 |
| 2135 __ Bind(&miss); |
| 2136 __ LoadIsolate(R2); |
| 2137 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
| 2138 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 2139 __ Ret(); |
| 2140 } |
| 2141 |
2098 } // namespace dart | 2142 } // namespace dart |
2099 | 2143 |
2100 #endif // defined TARGET_ARCH_ARM | 2144 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |