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_X64) | 6 #if defined(TARGET_ARCH_X64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 // miss-handler may return null. | 503 // miss-handler may return null. |
504 __ CompareObject(RAX, Object::null_object()); | 504 __ CompareObject(RAX, Object::null_object()); |
505 __ j(NOT_EQUAL, call_target_function); | 505 __ j(NOT_EQUAL, call_target_function); |
506 __ EnterStubFrame(); | 506 __ EnterStubFrame(); |
507 // Load the receiver. | 507 // Load the receiver. |
508 __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 508 __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
509 __ movq(RAX, Address( | 509 __ movq(RAX, Address( |
510 RBP, RDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize)); | 510 RBP, RDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize)); |
511 __ PushObject(Object::null_object()); // Setup space on stack for result. | 511 __ PushObject(Object::null_object()); // Setup space on stack for result. |
512 __ pushq(RAX); // Receiver. | 512 __ pushq(RAX); // Receiver. |
513 __ pushq(RBX); | 513 __ pushq(RBX); // ICData/MegamorphicCache. |
514 __ pushq(R10); // Arguments descriptor array. | 514 __ pushq(R10); // Arguments descriptor array. |
515 __ movq(R10, RDI); | 515 __ movq(R10, RDI); |
516 // EDX: Smi-tagged arguments array length. | 516 // EDX: Smi-tagged arguments array length. |
517 PushArgumentsArray(assembler); | 517 PushArgumentsArray(assembler); |
518 const intptr_t kNumArgs = 4; | 518 const intptr_t kNumArgs = 4; |
519 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); | 519 __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs); |
520 __ Drop(4); | 520 __ Drop(4); |
521 __ popq(RAX); // Return value. | 521 __ popq(RAX); // Return value. |
522 __ LeaveStubFrame(); | 522 __ LeaveStubFrame(); |
523 __ ret(); | 523 __ ret(); |
(...skipping 1557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2081 const Register left = RAX; | 2081 const Register left = RAX; |
2082 const Register right = RDX; | 2082 const Register right = RDX; |
2083 | 2083 |
2084 __ movq(left, Address(RSP, 2 * kWordSize)); | 2084 __ movq(left, Address(RSP, 2 * kWordSize)); |
2085 __ movq(right, Address(RSP, 1 * kWordSize)); | 2085 __ movq(right, Address(RSP, 1 * kWordSize)); |
2086 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2086 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2087 __ ret(); | 2087 __ ret(); |
2088 } | 2088 } |
2089 | 2089 |
2090 | 2090 |
2091 void StubCode::EmitMegamorphicLookup( | 2091 void StubCode::EmitMegamorphicLookup(Assembler* assembler) { |
2092 Assembler* assembler, Register receiver, Register cache, Register target) { | 2092 __ LoadTaggedClassIdMayBeSmi(RAX, RDI); |
2093 ASSERT((cache != RAX) && (cache != RDI)); | |
2094 __ LoadTaggedClassIdMayBeSmi(RAX, receiver); | |
2095 // RAX: class ID of the receiver (smi). | 2093 // RAX: class ID of the receiver (smi). |
2096 __ movq(RDI, FieldAddress(cache, MegamorphicCache::buckets_offset())); | 2094 __ movq(R10, |
2097 __ movq(RBX, FieldAddress(cache, MegamorphicCache::mask_offset())); | 2095 FieldAddress(RBX, MegamorphicCache::arguments_descriptor_offset())); |
| 2096 __ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset())); |
| 2097 __ movq(R9, FieldAddress(RBX, MegamorphicCache::mask_offset())); |
2098 // RDI: cache buckets array. | 2098 // RDI: cache buckets array. |
2099 // RBX: mask. | 2099 // RBX: mask. |
2100 __ movq(RCX, RAX); | 2100 __ movq(RCX, RAX); |
2101 | 2101 |
2102 Label loop, update, call_target_function; | 2102 Label loop, update, load_target_function; |
2103 __ jmp(&loop); | 2103 __ jmp(&loop); |
2104 | 2104 |
2105 __ Bind(&update); | 2105 __ Bind(&update); |
2106 __ AddImmediate(RCX, Immediate(Smi::RawValue(1))); | 2106 __ AddImmediate(RCX, Immediate(Smi::RawValue(1))); |
2107 __ Bind(&loop); | 2107 __ Bind(&loop); |
2108 __ andq(RCX, RBX); | 2108 __ andq(RCX, R9); |
2109 const intptr_t base = Array::data_offset(); | 2109 const intptr_t base = Array::data_offset(); |
2110 // RCX is smi tagged, but table entries are two words, so TIMES_8. | 2110 // RCX is smi tagged, but table entries are two words, so TIMES_8. |
2111 __ movq(RDX, FieldAddress(RDI, RCX, TIMES_8, base)); | 2111 __ movq(RDX, FieldAddress(RDI, RCX, TIMES_8, base)); |
2112 | 2112 |
2113 ASSERT(kIllegalCid == 0); | 2113 ASSERT(kIllegalCid == 0); |
2114 __ testq(RDX, RDX); | 2114 __ testq(RDX, RDX); |
2115 __ j(ZERO, &call_target_function, Assembler::kNearJump); | 2115 __ j(ZERO, &load_target_function, Assembler::kNearJump); |
2116 __ cmpq(RDX, RAX); | 2116 __ cmpq(RDX, RAX); |
2117 __ j(NOT_EQUAL, &update, Assembler::kNearJump); | 2117 __ j(NOT_EQUAL, &update, Assembler::kNearJump); |
2118 | 2118 |
2119 __ Bind(&call_target_function); | 2119 __ Bind(&load_target_function); |
2120 // Call the target found in the cache. For a class id match, this is a | 2120 // Call the target found in the cache. For a class id match, this is a |
2121 // proper target for the given name and arguments descriptor. If the | 2121 // proper target for the given name and arguments descriptor. If the |
2122 // illegal class id was found, the target is a cache miss handler that can | 2122 // illegal class id was found, the target is a cache miss handler that can |
2123 // be invoked as a normal Dart function. | 2123 // be invoked as a normal Dart function. |
2124 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize)); | 2124 __ movq(RAX, FieldAddress(RDI, RCX, TIMES_8, base + kWordSize)); |
| 2125 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
2125 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | 2126 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
2126 __ movq(target, FieldAddress(RAX, Function::entry_point_offset())); | |
2127 } | 2127 } |
2128 | 2128 |
2129 | 2129 |
2130 // Called from megamorphic calls. | 2130 // Called from megamorphic calls. |
2131 // RDI: receiver. | 2131 // RDI: receiver |
2132 // RBX: lookup cache. | 2132 // RBX: MegamorphicCache (preserved) |
2133 // Result: | 2133 // Result: |
2134 // RCX: entry point. | 2134 // RCX: target entry point |
| 2135 // CODE_REG: target Code |
| 2136 // R10: arguments descriptor |
2135 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { | 2137 void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) { |
2136 EmitMegamorphicLookup(assembler, RDI, RBX, RCX); | 2138 EmitMegamorphicLookup(assembler); |
2137 __ ret(); | 2139 __ ret(); |
2138 } | 2140 } |
2139 | 2141 |
| 2142 |
| 2143 // Called from switchable IC calls. |
| 2144 // RDI: receiver |
| 2145 // RBX: ICData (preserved) |
| 2146 // Result: |
| 2147 // RCX: target entry point |
| 2148 // CODE_REG: target Code object |
| 2149 // R10: arguments descriptor |
| 2150 void StubCode::GenerateICLookupStub(Assembler* assembler) { |
| 2151 Label loop, found, miss; |
| 2152 |
| 2153 __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset())); |
| 2154 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
| 2155 __ leaq(R13, FieldAddress(R13, Array::data_offset())); |
| 2156 // R13: first IC entry |
| 2157 __ LoadTaggedClassIdMayBeSmi(RAX, RDI); |
| 2158 // RAX: receiver cid as Smi |
| 2159 |
| 2160 __ Bind(&loop); |
| 2161 __ movq(R9, Address(R13, 0)); |
| 2162 __ cmpq(RAX, R9); |
| 2163 __ j(EQUAL, &found, Assembler::kNearJump); |
| 2164 |
| 2165 ASSERT(Smi::RawValue(kIllegalCid) == 0); |
| 2166 __ cmpq(R9, R9); |
| 2167 __ j(EQUAL, &miss, Assembler::kNearJump); |
| 2168 |
| 2169 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
| 2170 __ addq(R13, Immediate(entry_length)); // Next entry. |
| 2171 __ jmp(&loop); |
| 2172 |
| 2173 __ Bind(&found); |
| 2174 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; |
| 2175 __ movq(RAX, Address(R13, target_offset)); |
| 2176 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); |
| 2177 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); |
| 2178 __ ret(); |
| 2179 |
| 2180 __ Bind(&miss); |
| 2181 __ LoadIsolate(RAX); |
| 2182 __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset())); |
| 2183 __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset())); |
| 2184 __ ret(); |
| 2185 } |
| 2186 |
2140 } // namespace dart | 2187 } // namespace dart |
2141 | 2188 |
2142 #endif // defined TARGET_ARCH_X64 | 2189 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |