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

Side by Side Diff: runtime/vm/flow_graph_compiler_arm64.cc

Issue 1263573010: Use zone when allocating handles in FlowGraphCompiler assembling operations. Add profiling VM tags… (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: sync Created 5 years, 4 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_ia32.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 (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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" // Needed here to get TARGET_ARCH_ARM64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64.
6 #if defined(TARGET_ARCH_ARM64) 6 #if defined(TARGET_ARCH_ARM64)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 intptr_t slot_ix = 0; 88 intptr_t slot_ix = 0;
89 Environment* current = deopt_env_; 89 Environment* current = deopt_env_;
90 90
91 // Emit all kMaterializeObject instructions describing objects to be 91 // Emit all kMaterializeObject instructions describing objects to be
92 // materialized on the deoptimization as a prefix to the deoptimization info. 92 // materialized on the deoptimization as a prefix to the deoptimization info.
93 EmitMaterializations(deopt_env_, builder); 93 EmitMaterializations(deopt_env_, builder);
94 94
95 // The real frame starts here. 95 // The real frame starts here.
96 builder->MarkFrameStart(); 96 builder->MarkFrameStart();
97 97
98 Zone* zone = compiler->zone();
99
98 // Current PP, FP, and PC. 100 // Current PP, FP, and PC.
99 builder->AddPp(Function::Handle(current->code().function()), slot_ix++); 101 builder->AddPp(Function::Handle(zone, current->code().function()), slot_ix++);
100 builder->AddPcMarker(Function::Handle(), slot_ix++); 102 builder->AddPcMarker(Function::Handle(zone), slot_ix++);
101 builder->AddCallerFp(slot_ix++); 103 builder->AddCallerFp(slot_ix++);
102 builder->AddReturnAddress(Function::Handle(current->code().function()), 104 builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
103 deopt_id(), 105 deopt_id(),
104 slot_ix++); 106 slot_ix++);
105 107
106 // Emit all values that are needed for materialization as a part of the 108 // Emit all values that are needed for materialization as a part of the
107 // expression stack for the bottom-most frame. This guarantees that GC 109 // expression stack for the bottom-most frame. This guarantees that GC
108 // will be able to find them during materialization. 110 // will be able to find them during materialization.
109 slot_ix = builder->EmitMaterializationArguments(slot_ix); 111 slot_ix = builder->EmitMaterializationArguments(slot_ix);
110 112
111 // For the innermost environment, set outgoing arguments and the locals. 113 // For the innermost environment, set outgoing arguments and the locals.
112 for (intptr_t i = current->Length() - 1; 114 for (intptr_t i = current->Length() - 1;
113 i >= current->fixed_parameter_count(); 115 i >= current->fixed_parameter_count();
114 i--) { 116 i--) {
115 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); 117 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
116 } 118 }
117 119
118 Environment* previous = current; 120 Environment* previous = current;
119 current = current->outer(); 121 current = current->outer();
120 while (current != NULL) { 122 while (current != NULL) {
121 // PP, FP, and PC. 123 // PP, FP, and PC.
122 builder->AddPp(Function::Handle(current->code().function()), slot_ix++); 124 builder->AddPp(Function::Handle(
123 builder->AddPcMarker(Function::Handle(previous->code().function()), 125 zone, current->code().function()), slot_ix++);
126 builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
124 slot_ix++); 127 slot_ix++);
125 builder->AddCallerFp(slot_ix++); 128 builder->AddCallerFp(slot_ix++);
126 129
127 // For any outer environment the deopt id is that of the call instruction 130 // For any outer environment the deopt id is that of the call instruction
128 // which is recorded in the outer environment. 131 // which is recorded in the outer environment.
129 builder->AddReturnAddress(Function::Handle(current->code().function()), 132 builder->AddReturnAddress(
130 Isolate::ToDeoptAfter(current->deopt_id()), 133 Function::Handle(zone, current->code().function()),
131 slot_ix++); 134 Isolate::ToDeoptAfter(current->deopt_id()),
135 slot_ix++);
132 136
133 // The values of outgoing arguments can be changed from the inlined call so 137 // The values of outgoing arguments can be changed from the inlined call so
134 // we must read them from the previous environment. 138 // we must read them from the previous environment.
135 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 139 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
136 builder->AddCopy(previous->ValueAt(i), 140 builder->AddCopy(previous->ValueAt(i),
137 previous->LocationAt(i), 141 previous->LocationAt(i),
138 slot_ix++); 142 slot_ix++);
139 } 143 }
140 144
141 // Set the locals, note that outgoing arguments are not in the environment. 145 // Set the locals, note that outgoing arguments are not in the environment.
142 for (intptr_t i = current->Length() - 1; 146 for (intptr_t i = current->Length() - 1;
143 i >= current->fixed_parameter_count(); 147 i >= current->fixed_parameter_count();
144 i--) { 148 i--) {
145 builder->AddCopy(current->ValueAt(i), 149 builder->AddCopy(current->ValueAt(i),
146 current->LocationAt(i), 150 current->LocationAt(i),
147 slot_ix++); 151 slot_ix++);
148 } 152 }
149 153
150 // Iterate on the outer environment. 154 // Iterate on the outer environment.
151 previous = current; 155 previous = current;
152 current = current->outer(); 156 current = current->outer();
153 } 157 }
154 // The previous pointer is now the outermost environment. 158 // The previous pointer is now the outermost environment.
155 ASSERT(previous != NULL); 159 ASSERT(previous != NULL);
156 160
157 // For the outermost environment, set caller PC, caller PP, and caller FP. 161 // For the outermost environment, set caller PC, caller PP, and caller FP.
158 builder->AddCallerPp(slot_ix++); 162 builder->AddCallerPp(slot_ix++);
159 // PC marker. 163 // PC marker.
160 builder->AddPcMarker(Function::Handle(previous->code().function()), 164 builder->AddPcMarker(Function::Handle(zone, previous->code().function()),
161 slot_ix++); 165 slot_ix++);
162 builder->AddCallerFp(slot_ix++); 166 builder->AddCallerFp(slot_ix++);
163 builder->AddCallerPc(slot_ix++); 167 builder->AddCallerPc(slot_ix++);
164 168
165 // For the outermost environment, set the incoming arguments. 169 // For the outermost environment, set the incoming arguments.
166 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 170 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
167 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); 171 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
168 } 172 }
169 173
170 return builder->CreateDeoptInfo(deopt_table); 174 return builder->CreateDeoptInfo(deopt_table);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( 217 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
214 TypeTestStubKind test_kind, 218 TypeTestStubKind test_kind,
215 Register instance_reg, 219 Register instance_reg,
216 Register type_arguments_reg, 220 Register type_arguments_reg,
217 Register temp_reg, 221 Register temp_reg,
218 Label* is_instance_lbl, 222 Label* is_instance_lbl,
219 Label* is_not_instance_lbl) { 223 Label* is_not_instance_lbl) {
220 ASSERT(instance_reg == R0); 224 ASSERT(instance_reg == R0);
221 ASSERT(temp_reg == kNoRegister); // Unused on ARM. 225 ASSERT(temp_reg == kNoRegister); // Unused on ARM.
222 const SubtypeTestCache& type_test_cache = 226 const SubtypeTestCache& type_test_cache =
223 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 227 SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
224 __ LoadUniqueObject(R2, type_test_cache); 228 __ LoadUniqueObject(R2, type_test_cache);
225 if (test_kind == kTestTypeOneArg) { 229 if (test_kind == kTestTypeOneArg) {
226 ASSERT(type_arguments_reg == kNoRegister); 230 ASSERT(type_arguments_reg == kNoRegister);
227 __ LoadObject(R1, Object::null_object()); 231 __ LoadObject(R1, Object::null_object());
228 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); 232 __ BranchLink(&StubCode::Subtype1TestCacheLabel());
229 } else if (test_kind == kTestTypeTwoArgs) { 233 } else if (test_kind == kTestTypeTwoArgs) {
230 ASSERT(type_arguments_reg == kNoRegister); 234 ASSERT(type_arguments_reg == kNoRegister);
231 __ LoadObject(R1, Object::null_object()); 235 __ LoadObject(R1, Object::null_object());
232 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); 236 __ BranchLink(&StubCode::Subtype2TestCacheLabel());
233 } else if (test_kind == kTestTypeThreeArgs) { 237 } else if (test_kind == kTestTypeThreeArgs) {
(...skipping 14 matching lines...) Expand all
248 // R0: instance being type checked (preserved). 252 // R0: instance being type checked (preserved).
249 // Clobbers R2. 253 // Clobbers R2.
250 RawSubtypeTestCache* 254 RawSubtypeTestCache*
251 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( 255 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
252 intptr_t token_pos, 256 intptr_t token_pos,
253 const AbstractType& type, 257 const AbstractType& type,
254 Label* is_instance_lbl, 258 Label* is_instance_lbl,
255 Label* is_not_instance_lbl) { 259 Label* is_not_instance_lbl) {
256 __ Comment("InstantiatedTypeWithArgumentsTest"); 260 __ Comment("InstantiatedTypeWithArgumentsTest");
257 ASSERT(type.IsInstantiated()); 261 ASSERT(type.IsInstantiated());
258 const Class& type_class = Class::ZoneHandle(type.type_class()); 262 const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
259 ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass()); 263 ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
260 const Register kInstanceReg = R0; 264 const Register kInstanceReg = R0;
261 Error& malformed_error = Error::Handle(); 265 Error& malformed_error = Error::Handle(zone());
262 const Type& int_type = Type::Handle(Type::IntType()); 266 const Type& int_type = Type::Handle(zone(), Type::IntType());
263 const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error); 267 const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
264 // Malformed type should have been handled at graph construction time. 268 // Malformed type should have been handled at graph construction time.
265 ASSERT(smi_is_ok || malformed_error.IsNull()); 269 ASSERT(smi_is_ok || malformed_error.IsNull());
266 __ tsti(kInstanceReg, Immediate(kSmiTagMask)); 270 __ tsti(kInstanceReg, Immediate(kSmiTagMask));
267 if (smi_is_ok) { 271 if (smi_is_ok) {
268 __ b(is_instance_lbl, EQ); 272 __ b(is_instance_lbl, EQ);
269 } else { 273 } else {
270 __ b(is_not_instance_lbl, EQ); 274 __ b(is_not_instance_lbl, EQ);
271 } 275 }
272 const intptr_t num_type_args = type_class.NumTypeArguments(); 276 const intptr_t num_type_args = type_class.NumTypeArguments();
273 const intptr_t num_type_params = type_class.NumTypeParameters(); 277 const intptr_t num_type_params = type_class.NumTypeParameters();
274 const intptr_t from_index = num_type_args - num_type_params; 278 const intptr_t from_index = num_type_args - num_type_params;
275 const TypeArguments& type_arguments = 279 const TypeArguments& type_arguments =
276 TypeArguments::ZoneHandle(type.arguments()); 280 TypeArguments::ZoneHandle(zone(), type.arguments());
277 const bool is_raw_type = type_arguments.IsNull() || 281 const bool is_raw_type = type_arguments.IsNull() ||
278 type_arguments.IsRaw(from_index, num_type_params); 282 type_arguments.IsRaw(from_index, num_type_params);
279 // Signature class is an instantiated parameterized type. 283 // Signature class is an instantiated parameterized type.
280 if (!type_class.IsSignatureClass()) { 284 if (!type_class.IsSignatureClass()) {
281 if (is_raw_type) { 285 if (is_raw_type) {
282 const Register kClassIdReg = R2; 286 const Register kClassIdReg = R2;
283 // dynamic type argument, check only classes. 287 // dynamic type argument, check only classes.
284 __ LoadClassId(kClassIdReg, kInstanceReg); 288 __ LoadClassId(kClassIdReg, kInstanceReg);
285 __ CompareImmediate(kClassIdReg, type_class.id()); 289 __ CompareImmediate(kClassIdReg, type_class.id());
286 __ b(is_instance_lbl, EQ); 290 __ b(is_instance_lbl, EQ);
287 // List is a very common case. 291 // List is a very common case.
288 if (IsListClass(type_class)) { 292 if (IsListClass(type_class)) {
289 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); 293 GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
290 } 294 }
291 return GenerateSubtype1TestCacheLookup( 295 return GenerateSubtype1TestCacheLookup(
292 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 296 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
293 } 297 }
294 // If one type argument only, check if type argument is Object or dynamic. 298 // If one type argument only, check if type argument is Object or dynamic.
295 if (type_arguments.Length() == 1) { 299 if (type_arguments.Length() == 1) {
296 const AbstractType& tp_argument = AbstractType::ZoneHandle( 300 const AbstractType& tp_argument = AbstractType::ZoneHandle(
297 type_arguments.TypeAt(0)); 301 zone(), type_arguments.TypeAt(0));
298 ASSERT(!tp_argument.IsMalformed()); 302 ASSERT(!tp_argument.IsMalformed());
299 if (tp_argument.IsType()) { 303 if (tp_argument.IsType()) {
300 ASSERT(tp_argument.HasResolvedTypeClass()); 304 ASSERT(tp_argument.HasResolvedTypeClass());
301 // Check if type argument is dynamic or Object. 305 // Check if type argument is dynamic or Object.
302 const Type& object_type = Type::Handle(Type::ObjectType()); 306 const Type& object_type = Type::Handle(zone(), Type::ObjectType());
303 if (object_type.IsSubtypeOf(tp_argument, NULL)) { 307 if (object_type.IsSubtypeOf(tp_argument, NULL)) {
304 // Instance class test only necessary. 308 // Instance class test only necessary.
305 return GenerateSubtype1TestCacheLookup( 309 return GenerateSubtype1TestCacheLookup(
306 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 310 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
307 } 311 }
308 } 312 }
309 } 313 }
310 } 314 }
311 // Regular subtype test cache involving instance's type arguments. 315 // Regular subtype test cache involving instance's type arguments.
312 const Register kTypeArgumentsReg = kNoRegister; 316 const Register kTypeArgumentsReg = kNoRegister;
(...skipping 25 matching lines...) Expand all
338 // R0: instance being type checked (preserved). 342 // R0: instance being type checked (preserved).
339 // Clobbers R2, R3. 343 // Clobbers R2, R3.
340 // Returns true if there is a fallthrough. 344 // Returns true if there is a fallthrough.
341 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 345 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
342 intptr_t token_pos, 346 intptr_t token_pos,
343 const AbstractType& type, 347 const AbstractType& type,
344 Label* is_instance_lbl, 348 Label* is_instance_lbl,
345 Label* is_not_instance_lbl) { 349 Label* is_not_instance_lbl) {
346 __ Comment("InstantiatedTypeNoArgumentsTest"); 350 __ Comment("InstantiatedTypeNoArgumentsTest");
347 ASSERT(type.IsInstantiated()); 351 ASSERT(type.IsInstantiated());
348 const Class& type_class = Class::Handle(type.type_class()); 352 const Class& type_class = Class::Handle(zone(), type.type_class());
349 ASSERT(type_class.NumTypeArguments() == 0); 353 ASSERT(type_class.NumTypeArguments() == 0);
350 354
351 const Register kInstanceReg = R0; 355 const Register kInstanceReg = R0;
352 __ tsti(kInstanceReg, Immediate(kSmiTagMask)); 356 __ tsti(kInstanceReg, Immediate(kSmiTagMask));
353 // If instance is Smi, check directly. 357 // If instance is Smi, check directly.
354 const Class& smi_class = Class::Handle(Smi::Class()); 358 const Class& smi_class = Class::Handle(zone(), Smi::Class());
355 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 359 if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
356 type_class, 360 type_class,
357 TypeArguments::Handle(), 361 TypeArguments::Handle(zone()),
358 NULL)) { 362 NULL)) {
359 __ b(is_instance_lbl, EQ); 363 __ b(is_instance_lbl, EQ);
360 } else { 364 } else {
361 __ b(is_not_instance_lbl, EQ); 365 __ b(is_not_instance_lbl, EQ);
362 } 366 }
363 // Compare if the classes are equal. 367 // Compare if the classes are equal.
364 const Register kClassIdReg = R2; 368 const Register kClassIdReg = R2;
365 __ LoadClassId(kClassIdReg, kInstanceReg); 369 __ LoadClassId(kClassIdReg, kInstanceReg);
366 __ CompareImmediate(kClassIdReg, type_class.id()); 370 __ CompareImmediate(kClassIdReg, type_class.id());
367 __ b(is_instance_lbl, EQ); 371 __ b(is_instance_lbl, EQ);
368 // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted 372 // See ClassFinalizer::ResolveSuperTypeAndInterfaces for list of restricted
369 // interfaces. 373 // interfaces.
370 // Bool interface can be implemented only by core class Bool. 374 // Bool interface can be implemented only by core class Bool.
371 if (type.IsBoolType()) { 375 if (type.IsBoolType()) {
372 __ CompareImmediate(kClassIdReg, kBoolCid); 376 __ CompareImmediate(kClassIdReg, kBoolCid);
373 __ b(is_instance_lbl, EQ); 377 __ b(is_instance_lbl, EQ);
374 __ b(is_not_instance_lbl); 378 __ b(is_not_instance_lbl);
375 return false; 379 return false;
376 } 380 }
377 if (type.IsFunctionType()) { 381 if (type.IsFunctionType()) {
378 // Check if instance is a closure. 382 // Check if instance is a closure.
379 __ LoadClassById(R3, kClassIdReg); 383 __ LoadClassById(R3, kClassIdReg);
380 __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset()); 384 __ LoadFieldFromOffset(R3, R3, Class::signature_function_offset());
381 __ CompareObject(R3, Object::null_object()); 385 __ CompareObject(R3, Object::null_object());
382 __ b(is_instance_lbl, NE); 386 __ b(is_instance_lbl, NE);
383 } 387 }
384 // Custom checking for numbers (Smi, Mint, Bigint and Double). 388 // Custom checking for numbers (Smi, Mint, Bigint and Double).
385 // Note that instance is not Smi (checked above). 389 // Note that instance is not Smi (checked above).
386 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) { 390 if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
387 GenerateNumberTypeCheck( 391 GenerateNumberTypeCheck(
388 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl); 392 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
389 return false; 393 return false;
390 } 394 }
391 if (type.IsStringType()) { 395 if (type.IsStringType()) {
392 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 396 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
393 return false; 397 return false;
394 } 398 }
395 // Otherwise fallthrough. 399 // Otherwise fallthrough.
396 return true; 400 return true;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 // Load instantiator (or null) and instantiator type arguments on stack. 449 // Load instantiator (or null) and instantiator type arguments on stack.
446 __ ldr(R1, Address(SP)); // Get instantiator type arguments. 450 __ ldr(R1, Address(SP)); // Get instantiator type arguments.
447 // R1: instantiator type arguments. 451 // R1: instantiator type arguments.
448 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 452 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
449 __ CompareObject(R1, Object::null_object()); 453 __ CompareObject(R1, Object::null_object());
450 __ b(is_instance_lbl, EQ); 454 __ b(is_instance_lbl, EQ);
451 __ LoadFieldFromOffset( 455 __ LoadFieldFromOffset(
452 R2, R1, TypeArguments::type_at_offset(type_param.index())); 456 R2, R1, TypeArguments::type_at_offset(type_param.index()));
453 // R2: concrete type of type. 457 // R2: concrete type of type.
454 // Check if type argument is dynamic. 458 // Check if type argument is dynamic.
455 __ CompareObject(R2, Type::ZoneHandle(Type::DynamicType())); 459 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::DynamicType()));
456 __ b(is_instance_lbl, EQ); 460 __ b(is_instance_lbl, EQ);
457 __ CompareObject(R2, Type::ZoneHandle(Type::ObjectType())); 461 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::ObjectType()));
458 __ b(is_instance_lbl, EQ); 462 __ b(is_instance_lbl, EQ);
459 463
460 // For Smi check quickly against int and num interfaces. 464 // For Smi check quickly against int and num interfaces.
461 Label not_smi; 465 Label not_smi;
462 __ tsti(R0, Immediate(kSmiTagMask)); // Value is Smi? 466 __ tsti(R0, Immediate(kSmiTagMask)); // Value is Smi?
463 __ b(&not_smi, NE); 467 __ b(&not_smi, NE);
464 __ CompareObject(R2, Type::ZoneHandle(Type::IntType())); 468 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::IntType()));
465 __ b(is_instance_lbl, EQ); 469 __ b(is_instance_lbl, EQ);
466 __ CompareObject(R2, Type::ZoneHandle(Type::Number())); 470 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::Number()));
467 __ b(is_instance_lbl, EQ); 471 __ b(is_instance_lbl, EQ);
468 // Smi must be handled in runtime. 472 // Smi must be handled in runtime.
469 Label fall_through; 473 Label fall_through;
470 __ b(&fall_through); 474 __ b(&fall_through);
471 475
472 __ Bind(&not_smi); 476 __ Bind(&not_smi);
473 // R1: instantiator type arguments. 477 // R1: instantiator type arguments.
474 // R0: instance. 478 // R0: instance.
475 const Register kInstanceReg = R0; 479 const Register kInstanceReg = R0;
476 const Register kTypeArgumentsReg = R1; 480 const Register kTypeArgumentsReg = R1;
477 const Register kTempReg = kNoRegister; 481 const Register kTempReg = kNoRegister;
478 const SubtypeTestCache& type_test_cache = 482 const SubtypeTestCache& type_test_cache =
479 SubtypeTestCache::ZoneHandle( 483 SubtypeTestCache::ZoneHandle(zone(),
480 GenerateCallSubtypeTestStub(kTestTypeThreeArgs, 484 GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
481 kInstanceReg, 485 kInstanceReg,
482 kTypeArgumentsReg, 486 kTypeArgumentsReg,
483 kTempReg, 487 kTempReg,
484 is_instance_lbl, 488 is_instance_lbl,
485 is_not_instance_lbl)); 489 is_not_instance_lbl));
486 __ Bind(&fall_through); 490 __ Bind(&fall_through);
487 return type_test_cache.raw(); 491 return type_test_cache.raw();
488 } 492 }
489 if (type.IsType()) { 493 if (type.IsType()) {
(...skipping 30 matching lines...) Expand all
520 const AbstractType& type, 524 const AbstractType& type,
521 Label* is_instance_lbl, 525 Label* is_instance_lbl,
522 Label* is_not_instance_lbl) { 526 Label* is_not_instance_lbl) {
523 __ Comment("InlineInstanceof"); 527 __ Comment("InlineInstanceof");
524 if (type.IsVoidType()) { 528 if (type.IsVoidType()) {
525 // A non-null value is returned from a void function, which will result in a 529 // A non-null value is returned from a void function, which will result in a
526 // type error. A null value is handled prior to executing this inline code. 530 // type error. A null value is handled prior to executing this inline code.
527 return SubtypeTestCache::null(); 531 return SubtypeTestCache::null();
528 } 532 }
529 if (type.IsInstantiated()) { 533 if (type.IsInstantiated()) {
530 const Class& type_class = Class::ZoneHandle(type.type_class()); 534 const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
531 // A class equality check is only applicable with a dst type of a 535 // A class equality check is only applicable with a dst type of a
532 // non-parameterized class, non-signature class, or with a raw dst type of 536 // non-parameterized class, non-signature class, or with a raw dst type of
533 // a parameterized class. 537 // a parameterized class.
534 if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) { 538 if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
535 return GenerateInstantiatedTypeWithArgumentsTest(token_pos, 539 return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
536 type, 540 type,
537 is_instance_lbl, 541 is_instance_lbl,
538 is_not_instance_lbl); 542 is_not_instance_lbl);
539 // Fall through to runtime call. 543 // Fall through to runtime call.
540 } 544 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 // return false here if the instance is null (and if the type is 594 // return false here if the instance is null (and if the type is
591 // instantiated). 595 // instantiated).
592 // We can only inline this null check if the type is instantiated at compile 596 // We can only inline this null check if the type is instantiated at compile
593 // time, since an uninstantiated type at compile time could be Object or 597 // time, since an uninstantiated type at compile time could be Object or
594 // dynamic at run time. 598 // dynamic at run time.
595 __ CompareObject(R0, Object::null_object()); 599 __ CompareObject(R0, Object::null_object());
596 __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ); 600 __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ);
597 } 601 }
598 602
599 // Generate inline instanceof test. 603 // Generate inline instanceof test.
600 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 604 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
601 test_cache = GenerateInlineInstanceof(token_pos, type, 605 test_cache = GenerateInlineInstanceof(token_pos, type,
602 &is_instance, &is_not_instance); 606 &is_instance, &is_not_instance);
603 607
604 // test_cache is null if there is no fall-through. 608 // test_cache is null if there is no fall-through.
605 Label done; 609 Label done;
606 if (!test_cache.IsNull()) { 610 if (!test_cache.IsNull()) {
607 // Generate runtime call. 611 // Generate runtime call.
608 // Load instantiator (R2) and its type arguments (R1). 612 // Load instantiator (R2) and its type arguments (R1).
609 __ ldr(R1, Address(SP, 0 * kWordSize)); 613 __ ldr(R1, Address(SP, 0 * kWordSize));
610 __ ldr(R2, Address(SP, 1 * kWordSize)); 614 __ ldr(R2, Address(SP, 1 * kWordSize));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 __ brk(0); 693 __ brk(0);
690 694
691 __ Bind(&is_assignable); // For a null object. 695 __ Bind(&is_assignable); // For a null object.
692 // Restore instantiator (R2) and its type arguments (R1). 696 // Restore instantiator (R2) and its type arguments (R1).
693 __ Pop(R1); 697 __ Pop(R1);
694 __ Pop(R2); 698 __ Pop(R2);
695 return; 699 return;
696 } 700 }
697 701
698 // Generate inline type check, linking to runtime call if not assignable. 702 // Generate inline type check, linking to runtime call if not assignable.
699 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 703 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
700 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 704 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
701 &is_assignable, &runtime_call); 705 &is_assignable, &runtime_call);
702 706
703 __ Bind(&runtime_call); 707 __ Bind(&runtime_call);
704 // Load instantiator (R2) and its type arguments (R1). 708 // Load instantiator (R2) and its type arguments (R1).
705 __ ldr(R1, Address(SP)); 709 __ ldr(R1, Address(SP));
706 __ ldr(R2, Address(SP, 1 * kWordSize)); 710 __ ldr(R2, Address(SP, 1 * kWordSize));
707 __ PushObject(Object::null_object()); // Make room for the result. 711 __ PushObject(Object::null_object()); // Make room for the result.
708 __ Push(R0); // Push the source object. 712 __ Push(R0); // Push the source object.
709 __ PushObject(dst_type); // Push the type of the destination. 713 __ PushObject(dst_type); // Push the type of the destination.
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 // Point to next named entry. 855 // Point to next named entry.
852 __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size())); 856 __ add(R6, R6, Operand(ArgumentsDescriptor::named_entry_size()));
853 // Negate and untag R5 so we can use in scaled address mode. 857 // Negate and untag R5 so we can use in scaled address mode.
854 __ subs(R5, ZR, Operand(R5, ASR, 1)); 858 __ subs(R5, ZR, Operand(R5, ASR, 1));
855 Address argument_addr(R7, R5, UXTX, Address::Scaled); // R5 is untagged. 859 Address argument_addr(R7, R5, UXTX, Address::Scaled); // R5 is untagged.
856 __ ldr(R5, argument_addr); 860 __ ldr(R5, argument_addr);
857 __ b(&assign_optional_parameter); 861 __ b(&assign_optional_parameter);
858 __ Bind(&load_default_value); 862 __ Bind(&load_default_value);
859 // Load R5 with default argument. 863 // Load R5 with default argument.
860 const Object& value = Object::ZoneHandle( 864 const Object& value = Object::ZoneHandle(
861 parsed_function().default_parameter_values().At( 865 zone(), parsed_function().default_parameter_values().At(
862 param_pos - num_fixed_params)); 866 param_pos - num_fixed_params));
863 __ LoadObject(R5, value); 867 __ LoadObject(R5, value);
864 __ Bind(&assign_optional_parameter); 868 __ Bind(&assign_optional_parameter);
865 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 869 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
866 // We do not use the final allocation index of the variable here, i.e. 870 // We do not use the final allocation index of the variable here, i.e.
867 // scope->VariableAt(i)->index(), because captured variables still need 871 // scope->VariableAt(i)->index(), because captured variables still need
868 // to be copied to the context that is not yet allocated. 872 // to be copied to the context that is not yet allocated.
869 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 873 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
870 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize); 874 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize);
871 } 875 }
(...skipping 14 matching lines...) Expand all
886 for (int i = 0; i < num_opt_pos_params; i++) { 890 for (int i = 0; i < num_opt_pos_params; i++) {
887 Label next_parameter; 891 Label next_parameter;
888 // Handle this optional positional parameter only if k or fewer positional 892 // Handle this optional positional parameter only if k or fewer positional
889 // arguments have been passed, where k is param_pos, the position of this 893 // arguments have been passed, where k is param_pos, the position of this
890 // optional parameter in the formal parameter list. 894 // optional parameter in the formal parameter list.
891 const int param_pos = num_fixed_params + i; 895 const int param_pos = num_fixed_params + i;
892 __ CompareImmediate(R8, param_pos); 896 __ CompareImmediate(R8, param_pos);
893 __ b(&next_parameter, GT); 897 __ b(&next_parameter, GT);
894 // Load R5 with default argument. 898 // Load R5 with default argument.
895 const Object& value = Object::ZoneHandle( 899 const Object& value = Object::ZoneHandle(
896 parsed_function().default_parameter_values().At(i)); 900 zone(), parsed_function().default_parameter_values().At(i));
897 __ LoadObject(R5, value); 901 __ LoadObject(R5, value);
898 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos]. 902 // Assign R5 to fp[kFirstLocalSlotFromFp - param_pos].
899 // We do not use the final allocation index of the variable here, i.e. 903 // We do not use the final allocation index of the variable here, i.e.
900 // scope->VariableAt(i)->index(), because captured variables still need 904 // scope->VariableAt(i)->index(), because captured variables still need
901 // to be copied to the context that is not yet allocated. 905 // to be copied to the context that is not yet allocated.
902 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 906 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
903 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize); 907 __ StoreToOffset(R5, FP, computed_param_pos * kWordSize);
904 __ Bind(&next_parameter); 908 __ Bind(&next_parameter);
905 } 909 }
906 if (check_correct_named_args) { 910 if (check_correct_named_args) {
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 } 1198 }
1195 1199
1196 1200
1197 void FlowGraphCompiler::EmitEdgeCounter() { 1201 void FlowGraphCompiler::EmitEdgeCounter() {
1198 // We do not check for overflow when incrementing the edge counter. The 1202 // We do not check for overflow when incrementing the edge counter. The
1199 // function should normally be optimized long before the counter can 1203 // function should normally be optimized long before the counter can
1200 // overflow; and though we do not reset the counters when we optimize or 1204 // overflow; and though we do not reset the counters when we optimize or
1201 // deoptimize, there is a bound on the number of 1205 // deoptimize, there is a bound on the number of
1202 // optimization/deoptimization cycles we will attempt. 1206 // optimization/deoptimization cycles we will attempt.
1203 ASSERT(assembler_->constant_pool_allowed()); 1207 ASSERT(assembler_->constant_pool_allowed());
1204 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); 1208 const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
1205 counter.SetAt(0, Smi::Handle(Smi::New(0))); 1209 counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
1206 __ Comment("Edge counter"); 1210 __ Comment("Edge counter");
1207 __ LoadUniqueObject(R0, counter); 1211 __ LoadUniqueObject(R0, counter);
1208 __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0)); 1212 __ LoadFieldFromOffset(TMP, R0, Array::element_offset(0));
1209 __ add(TMP, TMP, Operand(Smi::RawValue(1))); 1213 __ add(TMP, TMP, Operand(Smi::RawValue(1)));
1210 __ StoreFieldToOffset(TMP, R0, Array::element_offset(0)); 1214 __ StoreFieldToOffset(TMP, R0, Array::element_offset(0));
1211 } 1215 }
1212 1216
1213 1217
1214 void FlowGraphCompiler::EmitOptimizedInstanceCall( 1218 void FlowGraphCompiler::EmitOptimizedInstanceCall(
1215 ExternalLabel* target_label, 1219 ExternalLabel* target_label,
1216 const ICData& ic_data, 1220 const ICData& ic_data,
1217 intptr_t argument_count, 1221 intptr_t argument_count,
1218 intptr_t deopt_id, 1222 intptr_t deopt_id,
1219 intptr_t token_pos, 1223 intptr_t token_pos,
1220 LocationSummary* locs) { 1224 LocationSummary* locs) {
1221 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); 1225 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
1222 // Each ICData propagated from unoptimized to optimized code contains the 1226 // Each ICData propagated from unoptimized to optimized code contains the
1223 // function that corresponds to the Dart function of that IC call. Due 1227 // function that corresponds to the Dart function of that IC call. Due
1224 // to inlining in optimized code, that function may not correspond to the 1228 // to inlining in optimized code, that function may not correspond to the
1225 // top-level function (parsed_function().function()) which could be 1229 // top-level function (parsed_function().function()) which could be
1226 // reoptimized and which counter needs to be incremented. 1230 // reoptimized and which counter needs to be incremented.
1227 // Pass the function explicitly, it is used in IC stub. 1231 // Pass the function explicitly, it is used in IC stub.
1228 1232
1229 __ LoadObject(R6, parsed_function().function()); 1233 __ LoadObject(R6, parsed_function().function());
1230 __ LoadUniqueObject(R5, ic_data); 1234 __ LoadUniqueObject(R5, ic_data);
1231 GenerateDartCall(deopt_id, 1235 GenerateDartCall(deopt_id,
1232 token_pos, 1236 token_pos,
1233 target_label, 1237 target_label,
1234 RawPcDescriptors::kIcCall, 1238 RawPcDescriptors::kIcCall,
1235 locs); 1239 locs);
1236 __ Drop(argument_count); 1240 __ Drop(argument_count);
1237 } 1241 }
1238 1242
1239 1243
1240 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 1244 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
1241 const ICData& ic_data, 1245 const ICData& ic_data,
1242 intptr_t argument_count, 1246 intptr_t argument_count,
1243 intptr_t deopt_id, 1247 intptr_t deopt_id,
1244 intptr_t token_pos, 1248 intptr_t token_pos,
1245 LocationSummary* locs) { 1249 LocationSummary* locs) {
1246 ASSERT(Array::Handle(ic_data.arguments_descriptor()).Length() > 0); 1250 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0);
1247 __ LoadUniqueObject(R5, ic_data); 1251 __ LoadUniqueObject(R5, ic_data);
1248 GenerateDartCall(deopt_id, 1252 GenerateDartCall(deopt_id,
1249 token_pos, 1253 token_pos,
1250 target_label, 1254 target_label,
1251 RawPcDescriptors::kIcCall, 1255 RawPcDescriptors::kIcCall,
1252 locs); 1256 locs);
1253 __ Drop(argument_count); 1257 __ Drop(argument_count);
1254 } 1258 }
1255 1259
1256 1260
1257 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1261 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
1258 const ICData& ic_data, 1262 const ICData& ic_data,
1259 intptr_t argument_count, 1263 intptr_t argument_count,
1260 intptr_t deopt_id, 1264 intptr_t deopt_id,
1261 intptr_t token_pos, 1265 intptr_t token_pos,
1262 LocationSummary* locs) { 1266 LocationSummary* locs) {
1263 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table(); 1267 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
1264 const String& name = String::Handle(ic_data.target_name()); 1268 const String& name = String::Handle(zone(), ic_data.target_name());
1265 const Array& arguments_descriptor = 1269 const Array& arguments_descriptor =
1266 Array::ZoneHandle(ic_data.arguments_descriptor()); 1270 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1267 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1271 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1268 const MegamorphicCache& cache = 1272 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(
1269 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); 1273 zone(), table->Lookup(name, arguments_descriptor));
1270 const Register receiverR = R0; 1274 const Register receiverR = R0;
1271 const Register cacheR = R1; 1275 const Register cacheR = R1;
1272 const Register targetR = R1; 1276 const Register targetR = R1;
1273 __ LoadFromOffset(receiverR, SP, (argument_count - 1) * kWordSize); 1277 __ LoadFromOffset(receiverR, SP, (argument_count - 1) * kWordSize);
1274 __ LoadObject(cacheR, cache); 1278 __ LoadObject(cacheR, cache);
1275 1279
1276 if (FLAG_use_megamorphic_stub) { 1280 if (FLAG_use_megamorphic_stub) {
1277 __ BranchLink(&StubCode::MegamorphicLookupLabel()); 1281 __ BranchLink(&StubCode::MegamorphicLookupLabel());
1278 } else { 1282 } else {
1279 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); 1283 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1472 const Array& argument_names, 1476 const Array& argument_names,
1473 Label* failed, 1477 Label* failed,
1474 Label* match_found, 1478 Label* match_found,
1475 intptr_t deopt_id, 1479 intptr_t deopt_id,
1476 intptr_t token_index, 1480 intptr_t token_index,
1477 LocationSummary* locs) { 1481 LocationSummary* locs) {
1478 ASSERT(is_optimizing()); 1482 ASSERT(is_optimizing());
1479 1483
1480 __ Comment("EmitTestAndCall"); 1484 __ Comment("EmitTestAndCall");
1481 const Array& arguments_descriptor = 1485 const Array& arguments_descriptor =
1482 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, 1486 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
1483 argument_names)); 1487 argument_names));
1484 1488
1485 // Load receiver into R0. 1489 // Load receiver into R0.
1486 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); 1490 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize);
1487 __ LoadObject(R4, arguments_descriptor); 1491 __ LoadObject(R4, arguments_descriptor);
1488 1492
1489 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; 1493 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
1490 const intptr_t kNumChecks = ic_data.NumberOfChecks(); 1494 const intptr_t kNumChecks = ic_data.NumberOfChecks();
1491 1495
1492 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); 1496 ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
1493 1497
1494 Label after_smi_test; 1498 Label after_smi_test;
1495 __ tsti(R0, Immediate(kSmiTagMask)); 1499 __ tsti(R0, Immediate(kSmiTagMask));
1496 if (kFirstCheckIsSmi) { 1500 if (kFirstCheckIsSmi) {
1497 // Jump if receiver is not Smi. 1501 // Jump if receiver is not Smi.
1498 if (kNumChecks == 1) { 1502 if (kNumChecks == 1) {
1499 __ b(failed, NE); 1503 __ b(failed, NE);
1500 } else { 1504 } else {
1501 __ b(&after_smi_test, NE); 1505 __ b(&after_smi_test, NE);
1502 } 1506 }
1503 // Do not use the code from the function, but let the code be patched so 1507 // Do not use the code from the function, but let the code be patched so
1504 // that we can record the outgoing edges to other code. 1508 // that we can record the outgoing edges to other code.
1505 GenerateDartCall(deopt_id, 1509 GenerateDartCall(deopt_id,
1506 token_index, 1510 token_index,
1507 &StubCode::CallStaticFunctionLabel(), 1511 &StubCode::CallStaticFunctionLabel(),
1508 RawPcDescriptors::kOther, 1512 RawPcDescriptors::kOther,
1509 locs); 1513 locs);
1510 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); 1514 const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
1511 AddStaticCallTarget(function); 1515 AddStaticCallTarget(function);
1512 __ Drop(argument_count); 1516 __ Drop(argument_count);
1513 if (kNumChecks > 1) { 1517 if (kNumChecks > 1) {
1514 __ b(match_found); 1518 __ b(match_found);
1515 } 1519 }
1516 } else { 1520 } else {
1517 // Receiver is Smi, but Smi is not a valid class therefore fail. 1521 // Receiver is Smi, but Smi is not a valid class therefore fail.
1518 // (Smi class must be first in the list). 1522 // (Smi class must be first in the list).
1519 __ b(failed, EQ); 1523 __ b(failed, EQ);
1520 } 1524 }
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1836 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1840 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1837 __ PopDouble(reg); 1841 __ PopDouble(reg);
1838 } 1842 }
1839 1843
1840 1844
1841 #undef __ 1845 #undef __
1842 1846
1843 } // namespace dart 1847 } // namespace dart
1844 1848
1845 #endif // defined TARGET_ARCH_ARM64 1849 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm.cc ('k') | runtime/vm/flow_graph_compiler_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698