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 __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid))); | |
Florian Schneider
2015/11/04 01:27:10
Alternatively: testq(R9, R9)
plus adding the asser
rmacnak
2015/11/04 01:50:22
Done.
| |
2166 __ j(EQUAL, &miss, Assembler::kNearJump); | |
2167 | |
2168 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; | |
2169 __ addq(R13, Immediate(entry_length)); // Next entry. | |
2170 __ jmp(&loop); | |
2171 | |
2172 __ Bind(&found); | |
2173 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; | |
2174 __ movq(RAX, Address(R13, target_offset)); | |
2175 __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset())); | |
2176 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | |
2177 __ ret(); | |
2178 | |
2179 __ Bind(&miss); | |
2180 __ LoadIsolate(RAX); | |
2181 __ movq(RAX, Address(RAX, Isolate::ic_miss_function_offset())); | |
Florian Schneider
2015/11/04 01:27:10
Would it work to just store the code object StubCo
rmacnak
2015/11/04 01:50:22
It's not in the VM isolate so we can't use Thread.
| |
2182 __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset())); | |
2183 __ movq(CODE_REG, FieldAddress(RAX, Function::code_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 |