| 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 |