Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: src/a64/code-stubs-a64.cc

Issue 157503002: A64: Synchronize with r18444. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/code-stubs-a64.h ('k') | src/a64/codegen-a64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 static Register registers[] = { x0 }; 210 static Register registers[] = { x0 };
211 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); 211 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
212 descriptor->register_params_ = registers; 212 descriptor->register_params_ = registers;
213 descriptor->deoptimization_handler_ = 213 descriptor->deoptimization_handler_ =
214 FUNCTION_ADDR(CompareNilIC_Miss); 214 FUNCTION_ADDR(CompareNilIC_Miss);
215 descriptor->SetMissHandler( 215 descriptor->SetMissHandler(
216 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate)); 216 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate));
217 } 217 }
218 218
219 219
220 void BinaryOpICStub::InitializeInterfaceDescriptor(
221 Isolate* isolate,
222 CodeStubInterfaceDescriptor* descriptor) {
223 // x1: left operand
224 // x0: right operand
225 static Register registers[] = { x1, x0 };
226 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
227 descriptor->register_params_ = registers;
228 descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss);
229 descriptor->SetMissHandler(
230 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate));
231 }
232
233
234 static void InitializeArrayConstructorDescriptor( 220 static void InitializeArrayConstructorDescriptor(
235 Isolate* isolate, 221 Isolate* isolate,
236 CodeStubInterfaceDescriptor* descriptor, 222 CodeStubInterfaceDescriptor* descriptor,
237 int constant_stack_parameter_count) { 223 int constant_stack_parameter_count) {
238 // x1: function 224 // x1: function
239 // x2: type info cell with elements kind 225 // x2: type info cell with elements kind
240 // x0: number of arguments to the constructor function 226 // x0: number of arguments to the constructor function
241 static Register registers_variable_args[] = { x1, x2, x0 }; 227 static Register registers_variable_args[] = { x1, x2, x0 };
242 static Register registers_no_args[] = { x1, x2 }; 228 static Register registers_no_args[] = { x1, x2 };
243 229
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 // x1: key 353 // x1: key
368 // x2: receiver 354 // x2: receiver
369 static Register registers[] = { x0, x3, x1, x2 }; 355 static Register registers[] = { x0, x3, x1, x2 };
370 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); 356 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
371 descriptor->register_params_ = registers; 357 descriptor->register_params_ = registers;
372 descriptor->deoptimization_handler_ = 358 descriptor->deoptimization_handler_ =
373 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss); 359 FUNCTION_ADDR(ElementsTransitionAndStoreIC_Miss);
374 } 360 }
375 361
376 362
363 void BinaryOpICStub::InitializeInterfaceDescriptor(
364 Isolate* isolate,
365 CodeStubInterfaceDescriptor* descriptor) {
366 // x1: left operand
367 // x0: right operand
368 static Register registers[] = { x1, x0 };
369 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
370 descriptor->register_params_ = registers;
371 descriptor->deoptimization_handler_ = FUNCTION_ADDR(BinaryOpIC_Miss);
372 descriptor->SetMissHandler(
373 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate));
374 }
375
376
377 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor(
378 Isolate* isolate,
379 CodeStubInterfaceDescriptor* descriptor) {
380 // x2: allocation site
381 // x1: left operand
382 // x0: right operand
383 static Register registers[] = { x2, x1, x0 };
384 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
385 descriptor->register_params_ = registers;
386 descriptor->deoptimization_handler_ =
387 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite);
388 }
389
390
377 void NewStringAddStub::InitializeInterfaceDescriptor( 391 void NewStringAddStub::InitializeInterfaceDescriptor(
378 Isolate* isolate, 392 Isolate* isolate,
379 CodeStubInterfaceDescriptor* descriptor) { 393 CodeStubInterfaceDescriptor* descriptor) {
380 // x1: left operand 394 // x1: left operand
381 // x0: right operand 395 // x0: right operand
382 static Register registers[] = { x1, x0 }; 396 static Register registers[] = { x1, x0 };
383 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]); 397 descriptor->register_param_count_ = sizeof(registers) / sizeof(registers[0]);
384 descriptor->register_params_ = registers; 398 descriptor->register_params_ = registers;
385 descriptor->deoptimization_handler_ = 399 descriptor->deoptimization_handler_ =
386 Runtime::FunctionForId(Runtime::kStringAdd)->entry; 400 Runtime::FunctionForId(Runtime::kStringAdd)->entry;
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 1039
1026 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime( 1040 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(
1027 Isolate* isolate) { 1041 Isolate* isolate) {
1028 StoreBufferOverflowStub stub1(kDontSaveFPRegs); 1042 StoreBufferOverflowStub stub1(kDontSaveFPRegs);
1029 stub1.GetCode(isolate); 1043 stub1.GetCode(isolate);
1030 StoreBufferOverflowStub stub2(kSaveFPRegs); 1044 StoreBufferOverflowStub stub2(kSaveFPRegs);
1031 stub2.GetCode(isolate); 1045 stub2.GetCode(isolate);
1032 } 1046 }
1033 1047
1034 1048
1035 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
1036 // Untagged case:
1037 // Input: double in d0
1038 // Result: double in d0
1039 //
1040 // Tagged case:
1041 // Input: tagged value in jssp[0]
1042 // Result: tagged value in x0
1043
1044 const bool tagged = (argument_type_ == TAGGED);
1045
1046 Label calculate;
1047 Label invalid_cache;
1048 Register scratch0 = x10;
1049 Register scratch1 = x11;
1050 Register cache_entry = x12;
1051 Register hash = x13;
1052 Register hash_w = hash.W();
1053 Register input_double_bits = x14;
1054 Register input_tagged = x15;
1055 Register result_tagged = x0;
1056 FPRegister result_double = d0;
1057 FPRegister input_double = d0;
1058
1059 // First, get the input as a double, in an integer register (so we can
1060 // calculate a hash).
1061 if (tagged) {
1062 Label input_not_smi, loaded;
1063 // Load argument and check if it is a smi.
1064 __ Pop(input_tagged);
1065 __ JumpIfNotSmi(input_tagged, &input_not_smi);
1066
1067 // Input is a smi, so convert it to a double.
1068 __ SmiUntagToDouble(input_double, input_tagged);
1069 __ Fmov(input_double_bits, input_double);
1070 __ B(&loaded);
1071
1072 __ Bind(&input_not_smi);
1073 // Check if input is a HeapNumber.
1074 __ JumpIfNotHeapNumber(input_tagged, &calculate);
1075 // The input is a HeapNumber. Load it into input_double_bits.
1076 __ Ldr(input_double_bits,
1077 FieldMemOperand(input_tagged, HeapNumber::kValueOffset));
1078
1079 __ Bind(&loaded);
1080 } else {
1081 // Get the integer representation of the double.
1082 __ Fmov(input_double_bits, input_double);
1083 }
1084
1085 // Compute hash (the shifts are arithmetic):
1086 // h = (input_double_bits[31:0] ^ input_double_bits[63:32]);
1087 // h ^= h >> 16;
1088 // h ^= h >> 8;
1089 // h = h % cacheSize;
1090 __ Eor(hash, input_double_bits, Operand(input_double_bits, LSR, 32));
1091 __ Eor(hash_w, hash_w, Operand(hash_w, ASR, 16));
1092 __ Eor(hash_w, hash_w, Operand(hash_w, ASR, 8));
1093 __ And(hash_w, hash_w, TranscendentalCache::SubCache::kCacheSize - 1);
1094 STATIC_ASSERT(IS_POWER_OF_TWO(TranscendentalCache::SubCache::kCacheSize));
1095
1096 // d0 input_double Double input value (if UNTAGGED).
1097 // x13(w13) hash(_w) TranscendentalCache::hash(input).
1098 // x14 input_double_bits Input value as double bits.
1099 // x15 input_tagged Tagged input value (if TAGGED).
1100 Isolate* isolate = masm->isolate();
1101 ExternalReference cache_array =
1102 ExternalReference::transcendental_cache_array_address(isolate);
1103 int cache_array_index =
1104 type_ * sizeof(isolate->transcendental_cache()->caches_[0]);
1105
1106 __ Mov(cache_entry, Operand(cache_array));
1107 __ Ldr(cache_entry, MemOperand(cache_entry, cache_array_index));
1108
1109 // x12 cache_entry The address of the cache for type_.
1110 // If NULL, the cache hasn't been initialized yet, so go through runtime.
1111 __ Cbz(cache_entry, &invalid_cache);
1112
1113 #ifdef DEBUG
1114 // Check that the layout of cache elements match expectations.
1115 { TranscendentalCache::SubCache::Element test_elem[2];
1116 uintptr_t elem_start = reinterpret_cast<uintptr_t>(&test_elem[0]);
1117 uintptr_t elem2_start = reinterpret_cast<uintptr_t>(&test_elem[1]);
1118 uintptr_t elem_in0 = reinterpret_cast<uintptr_t>(&(test_elem[0].in[0]));
1119 uintptr_t elem_in1 = reinterpret_cast<uintptr_t>(&(test_elem[0].in[1]));
1120 uintptr_t elem_out = reinterpret_cast<uintptr_t>(&(test_elem[0].output));
1121 CHECK_EQ(16, elem2_start - elem_start); // Two uint_32s and a pointer.
1122 CHECK_EQ(0, elem_in0 - elem_start);
1123 CHECK_EQ(kIntSize, elem_in1 - elem_start);
1124 CHECK_EQ(2 * kIntSize, elem_out - elem_start);
1125 }
1126 #endif
1127
1128 // The (candidate) cached element is at cache[hash*16].
1129 __ Add(cache_entry, cache_entry, Operand(hash, LSL, 4));
1130 __ Ldp(scratch0, result_tagged, MemOperand(cache_entry));
1131 __ Cmp(scratch0, input_double_bits);
1132 __ B(&calculate, ne);
1133
1134 // Cache hit: Load the result and return.
1135
1136 __ IncrementCounter(isolate->counters()->transcendental_cache_hit(), 1,
1137 scratch0, scratch1);
1138 if (!tagged) {
1139 // result_tagged now already holds the tagged result from the cache, but we
1140 // need to untag it for the untagged case.
1141 __ Ldr(result_double, FieldMemOperand(result_tagged,
1142 HeapNumber::kValueOffset));
1143 }
1144 __ Ret();
1145
1146 // Cache miss: Calculate the result.
1147
1148 __ Bind(&calculate);
1149 __ IncrementCounter(isolate->counters()->transcendental_cache_miss(), 1,
1150 scratch0, scratch1);
1151 if (tagged) {
1152 __ Bind(&invalid_cache);
1153 __ Push(input_tagged);
1154 ExternalReference runtime_function = ExternalReference(RuntimeFunction(),
1155 masm->isolate());
1156 __ TailCallExternalReference(runtime_function, 1, 1);
1157 } else {
1158 Label gc_required;
1159 Label calculation_and_gc_required;
1160
1161 // Call a C function to calculate the result, then update the cache.
1162 // The following caller-saved registers need to be preserved for the call:
1163 // x12 cache_entry The address of the cache for type_.
1164 // x14 input_double_bits The bit representation of the input.
1165 // lr The return address of the stub.
1166 __ Push(cache_entry, input_double_bits, lr);
1167 ASSERT(input_double.Is(d0));
1168 { AllowExternalCallThatCantCauseGC scope(masm);
1169 __ CallCFunction(CFunction(isolate), 0, 1);
1170 }
1171 ASSERT(result_double.Is(d0));
1172 __ Pop(lr, input_double_bits, cache_entry);
1173
1174 // Try to update the cache.
1175 __ AllocateHeapNumber(result_tagged, &gc_required, scratch0, scratch1);
1176 __ Str(result_double, FieldMemOperand(result_tagged,
1177 HeapNumber::kValueOffset));
1178 __ Stp(input_double_bits, result_tagged, MemOperand(cache_entry));
1179 __ Ret();
1180
1181
1182 __ Bind(&invalid_cache);
1183 // Handle an invalid (uninitialized) cache by calling the runtime.
1184 // d0 input_double Double input value (if UNTAGGED).
1185 __ AllocateHeapNumber(result_tagged, &calculation_and_gc_required,
1186 scratch0, scratch1);
1187 __ Str(input_double, FieldMemOperand(result_tagged,
1188 HeapNumber::kValueOffset));
1189 { FrameScope scope(masm, StackFrame::INTERNAL);
1190 __ Push(result_tagged);
1191 __ CallRuntime(RuntimeFunction(), 1);
1192 }
1193 __ Ldr(result_double, FieldMemOperand(result_tagged,
1194 HeapNumber::kValueOffset));
1195 __ Ret();
1196
1197
1198 __ Bind(&calculation_and_gc_required);
1199 // Call C function to calculate the result and answer directly without
1200 // updating the cache.
1201 ASSERT(input_double.Is(d0));
1202 { AllowExternalCallThatCantCauseGC scope(masm);
1203 __ CallCFunction(CFunction(isolate), 0, 1);
1204 }
1205 ASSERT(result_double.Is(d0));
1206
1207
1208 // We got here because an allocation failed. Trigger a scavenging GC so that
1209 // future allocations will succeed.
1210 __ Bind(&gc_required);
1211 __ Push(result_double);
1212 { FrameScope scope(masm, StackFrame::INTERNAL);
1213 // Allocate an aligned object larger than a HeapNumber.
1214 int alloc_size = 2 * kPointerSize;
1215 ASSERT(alloc_size >= HeapNumber::kSize);
1216 __ Mov(scratch0, Operand(Smi::FromInt(alloc_size)));
1217 __ Push(scratch0);
1218 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1219 }
1220 __ Pop(result_double);
1221 __ Ret();
1222 }
1223 }
1224
1225
1226 ExternalReference TranscendentalCacheStub::CFunction(Isolate* isolate) {
1227 switch (type_) {
1228 // Add more cases when necessary.
1229 default:
1230 // There's no NULL ExternalReference, so fall into an existing case to
1231 // avoid compiler warnings about not having a return value.
1232 UNIMPLEMENTED();
1233 case TranscendentalCache::LOG:
1234 return ExternalReference::math_log_double_function(isolate);
1235 }
1236 }
1237
1238
1239 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
1240 switch (type_) {
1241 // Add more cases when necessary.
1242 case TranscendentalCache::LOG: return Runtime::kMath_log;
1243 default:
1244 UNIMPLEMENTED();
1245 return Runtime::kAbort;
1246 }
1247 }
1248
1249
1250 void MathPowStub::Generate(MacroAssembler* masm) { 1049 void MathPowStub::Generate(MacroAssembler* masm) {
1251 // Stack on entry: 1050 // Stack on entry:
1252 // jssp[0]: Exponent (as a tagged value). 1051 // jssp[0]: Exponent (as a tagged value).
1253 // jssp[1]: Base (as a tagged value). 1052 // jssp[1]: Base (as a tagged value).
1254 // 1053 //
1255 // The (tagged) result will be returned in x0, as a heap number. 1054 // The (tagged) result will be returned in x0, as a heap number.
1256 1055
1257 Register result_tagged = x0; 1056 Register result_tagged = x0;
1258 Register base_tagged = x10; 1057 Register base_tagged = x10;
1259 Register exponent_tagged = x11; 1058 Register exponent_tagged = x11;
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 // It is important that the following stubs are generated in this order 1302 // It is important that the following stubs are generated in this order
1504 // because pregenerated stubs can only call other pregenerated stubs. 1303 // because pregenerated stubs can only call other pregenerated stubs.
1505 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses 1304 // RecordWriteStub uses StoreBufferOverflowStub, which in turn uses
1506 // CEntryStub. 1305 // CEntryStub.
1507 CEntryStub::GenerateAheadOfTime(isolate); 1306 CEntryStub::GenerateAheadOfTime(isolate);
1508 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); 1307 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate);
1509 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); 1308 StubFailureTrampolineStub::GenerateAheadOfTime(isolate);
1510 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); 1309 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
1511 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); 1310 CreateAllocationSiteStub::GenerateAheadOfTime(isolate);
1512 BinaryOpICStub::GenerateAheadOfTime(isolate); 1311 BinaryOpICStub::GenerateAheadOfTime(isolate);
1312 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate);
1513 } 1313 }
1514 1314
1515 1315
1516 void CodeStub::GenerateFPStubs(Isolate* isolate) { 1316 void CodeStub::GenerateFPStubs(Isolate* isolate) {
1517 // Floating-point code doesn't get special handling in A64, so there's 1317 // Floating-point code doesn't get special handling in A64, so there's
1518 // nothing to do here. 1318 // nothing to do here.
1519 USE(isolate); 1319 USE(isolate);
1520 } 1320 }
1521 1321
1522 1322
(...skipping 3258 matching lines...) Expand 10 before | Expand all | Expand 10 after
4781 // sp[0] = right string 4581 // sp[0] = right string
4782 // sp[8] = left string. 4582 // sp[8] = left string.
4783 __ Push(left, right); 4583 __ Push(left, right);
4784 4584
4785 // Call the runtime. 4585 // Call the runtime.
4786 // Returns -1 (less), 0 (equal), or 1 (greater) tagged as a small integer. 4586 // Returns -1 (less), 0 (equal), or 1 (greater) tagged as a small integer.
4787 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 4587 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
4788 } 4588 }
4789 4589
4790 4590
4591 void BinaryOpICWithAllocationSiteStub::Generate(MacroAssembler* masm) {
4592 // ----------- S t a t e -------------
4593 // -- x1 : left
4594 // -- x0 : right
4595 // -- lr : return address
4596 // -----------------------------------
4597 Isolate* isolate = masm->isolate();
4598
4599 // Load x2 with the allocation site. We stick an undefined dummy value here
4600 // and replace it with the real allocation site later when we instantiate this
4601 // stub in BinaryOpICWithAllocationSiteStub::GetCodeCopyFromTemplate().
4602 __ LoadObject(x2, handle(isolate->heap()->undefined_value()));
4603
4604 // Make sure that we actually patched the allocation site.
4605 if (FLAG_debug_code) {
4606 __ AssertNotSmi(x2, kExpectedAllocationSite);
4607 __ Ldr(x10, FieldMemOperand(x2, HeapObject::kMapOffset));
4608 __ AssertRegisterIsRoot(x10, Heap::kAllocationSiteMapRootIndex,
4609 kExpectedAllocationSite);
4610 }
4611
4612 // Tail call into the stub that handles binary operations with allocation
4613 // sites.
4614 BinaryOpWithAllocationSiteStub stub(state_);
4615 __ TailCallStub(&stub);
4616 }
4617
4618
4791 void StringAddStub::Generate(MacroAssembler* masm) { 4619 void StringAddStub::Generate(MacroAssembler* masm) {
4792 Label call_runtime, call_builtin; 4620 Label call_runtime, call_builtin;
4793 Builtins::JavaScript builtin_id = Builtins::ADD; 4621 Builtins::JavaScript builtin_id = Builtins::ADD;
4794 4622
4795 Counters* counters = masm->isolate()->counters(); 4623 Counters* counters = masm->isolate()->counters();
4796 4624
4797 // Stack on entry: 4625 // Stack on entry:
4798 // sp[0]: second argument (right). 4626 // sp[0]: second argument (right).
4799 // sp[8]: first argument (left). 4627 // sp[8]: first argument (left).
4800 4628
(...skipping 1331 matching lines...) Expand 10 before | Expand all | Expand 10 after
6132 __ Bind(&fast_elements_case); 5960 __ Bind(&fast_elements_case);
6133 GenerateCase(masm, FAST_ELEMENTS); 5961 GenerateCase(masm, FAST_ELEMENTS);
6134 } 5962 }
6135 5963
6136 5964
6137 #undef __ 5965 #undef __
6138 5966
6139 } } // namespace v8::internal 5967 } } // namespace v8::internal
6140 5968
6141 #endif // V8_TARGET_ARCH_A64 5969 #endif // V8_TARGET_ARCH_A64
OLDNEW
« no previous file with comments | « src/a64/code-stubs-a64.h ('k') | src/a64/codegen-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698