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

Side by Side Diff: runtime/vm/flow_graph_compiler_ia32.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_arm64.cc ('k') | runtime/vm/flow_graph_compiler_mips.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) 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" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 intptr_t slot_ix = 0; 93 intptr_t slot_ix = 0;
94 Environment* current = deopt_env_; 94 Environment* current = deopt_env_;
95 95
96 // Emit all kMaterializeObject instructions describing objects to be 96 // Emit all kMaterializeObject instructions describing objects to be
97 // materialized on the deoptimization as a prefix to the deoptimization info. 97 // materialized on the deoptimization as a prefix to the deoptimization info.
98 EmitMaterializations(deopt_env_, builder); 98 EmitMaterializations(deopt_env_, builder);
99 99
100 // The real frame starts here. 100 // The real frame starts here.
101 builder->MarkFrameStart(); 101 builder->MarkFrameStart();
102 102
103 Zone* zone = compiler->zone();
104
103 // Callee's PC marker is not used anymore. Pass Code::null() to set to 0. 105 // Callee's PC marker is not used anymore. Pass Code::null() to set to 0.
104 builder->AddPcMarker(Function::Handle(), slot_ix++); 106 builder->AddPcMarker(Function::Handle(zone), slot_ix++);
105 107
106 // Current FP and PC. 108 // Current FP and PC.
107 builder->AddCallerFp(slot_ix++); 109 builder->AddCallerFp(slot_ix++);
108 builder->AddReturnAddress(Function::Handle(current->code().function()), 110 builder->AddReturnAddress(Function::Handle(zone, current->code().function()),
109 deopt_id(), 111 deopt_id(),
110 slot_ix++); 112 slot_ix++);
111 113
112 // Emit all values that are needed for materialization as a part of the 114 // Emit all values that are needed for materialization as a part of the
113 // expression stack for the bottom-most frame. This guarantees that GC 115 // expression stack for the bottom-most frame. This guarantees that GC
114 // will be able to find them during materialization. 116 // will be able to find them during materialization.
115 slot_ix = builder->EmitMaterializationArguments(slot_ix); 117 slot_ix = builder->EmitMaterializationArguments(slot_ix);
116 118
117 // For the innermost environment, set outgoing arguments and the locals. 119 // For the innermost environment, set outgoing arguments and the locals.
118 for (intptr_t i = current->Length() - 1; 120 for (intptr_t i = current->Length() - 1;
119 i >= current->fixed_parameter_count(); 121 i >= current->fixed_parameter_count();
120 i--) { 122 i--) {
121 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); 123 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
122 } 124 }
123 125
124 // Current PC marker and caller FP. 126 // Current PC marker and caller FP.
125 builder->AddPcMarker(Function::Handle(current->code().function()), slot_ix++); 127 builder->AddPcMarker(Function::Handle(
128 zone, current->code().function()), slot_ix++);
126 builder->AddCallerFp(slot_ix++); 129 builder->AddCallerFp(slot_ix++);
127 130
128 Environment* previous = current; 131 Environment* previous = current;
129 current = current->outer(); 132 current = current->outer();
130 while (current != NULL) { 133 while (current != NULL) {
131 // For any outer environment the deopt id is that of the call instruction 134 // For any outer environment the deopt id is that of the call instruction
132 // which is recorded in the outer environment. 135 // which is recorded in the outer environment.
133 builder->AddReturnAddress(Function::Handle(current->code().function()), 136 builder->AddReturnAddress(
134 Isolate::ToDeoptAfter(current->deopt_id()), 137 Function::Handle(zone, current->code().function()),
135 slot_ix++); 138 Isolate::ToDeoptAfter(current->deopt_id()),
139 slot_ix++);
136 140
137 // The values of outgoing arguments can be changed from the inlined call so 141 // The values of outgoing arguments can be changed from the inlined call so
138 // we must read them from the previous environment. 142 // we must read them from the previous environment.
139 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 143 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
140 builder->AddCopy(previous->ValueAt(i), 144 builder->AddCopy(previous->ValueAt(i),
141 previous->LocationAt(i), 145 previous->LocationAt(i),
142 slot_ix++); 146 slot_ix++);
143 } 147 }
144 148
145 // Set the locals, note that outgoing arguments are not in the environment. 149 // Set the locals, note that outgoing arguments are not in the environment.
146 for (intptr_t i = current->Length() - 1; 150 for (intptr_t i = current->Length() - 1;
147 i >= current->fixed_parameter_count(); 151 i >= current->fixed_parameter_count();
148 i--) { 152 i--) {
149 builder->AddCopy(current->ValueAt(i), 153 builder->AddCopy(current->ValueAt(i),
150 current->LocationAt(i), 154 current->LocationAt(i),
151 slot_ix++); 155 slot_ix++);
152 } 156 }
153 157
154 // PC marker and caller FP. 158 // PC marker and caller FP.
155 builder->AddPcMarker(Function::Handle(current->code().function()), 159 builder->AddPcMarker(Function::Handle(zone, current->code().function()),
156 slot_ix++); 160 slot_ix++);
157 builder->AddCallerFp(slot_ix++); 161 builder->AddCallerFp(slot_ix++);
158 162
159 // Iterate on the outer environment. 163 // Iterate on the outer environment.
160 previous = current; 164 previous = current;
161 current = current->outer(); 165 current = current->outer();
162 } 166 }
163 // The previous pointer is now the outermost environment. 167 // The previous pointer is now the outermost environment.
164 ASSERT(previous != NULL); 168 ASSERT(previous != NULL);
165 169
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 221
218 // Clobbers ECX. 222 // Clobbers ECX.
219 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( 223 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
220 TypeTestStubKind test_kind, 224 TypeTestStubKind test_kind,
221 Register instance_reg, 225 Register instance_reg,
222 Register type_arguments_reg, 226 Register type_arguments_reg,
223 Register temp_reg, 227 Register temp_reg,
224 Label* is_instance_lbl, 228 Label* is_instance_lbl,
225 Label* is_not_instance_lbl) { 229 Label* is_not_instance_lbl) {
226 const SubtypeTestCache& type_test_cache = 230 const SubtypeTestCache& type_test_cache =
227 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 231 SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
228 const Immediate& raw_null = 232 const Immediate& raw_null =
229 Immediate(reinterpret_cast<intptr_t>(Object::null())); 233 Immediate(reinterpret_cast<intptr_t>(Object::null()));
230 __ LoadObject(temp_reg, type_test_cache); 234 __ LoadObject(temp_reg, type_test_cache);
231 __ pushl(temp_reg); // Subtype test cache. 235 __ pushl(temp_reg); // Subtype test cache.
232 __ pushl(instance_reg); // Instance. 236 __ pushl(instance_reg); // Instance.
233 if (test_kind == kTestTypeOneArg) { 237 if (test_kind == kTestTypeOneArg) {
234 ASSERT(type_arguments_reg == kNoRegister); 238 ASSERT(type_arguments_reg == kNoRegister);
235 __ pushl(raw_null); 239 __ pushl(raw_null);
236 __ call(&StubCode::Subtype1TestCacheLabel()); 240 __ call(&StubCode::Subtype1TestCacheLabel());
237 } else if (test_kind == kTestTypeTwoArgs) { 241 } else if (test_kind == kTestTypeTwoArgs) {
(...skipping 23 matching lines...) Expand all
261 // EAX: instance (must survive). 265 // EAX: instance (must survive).
262 // Clobbers ECX, EDI. 266 // Clobbers ECX, EDI.
263 RawSubtypeTestCache* 267 RawSubtypeTestCache*
264 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( 268 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
265 intptr_t token_pos, 269 intptr_t token_pos,
266 const AbstractType& type, 270 const AbstractType& type,
267 Label* is_instance_lbl, 271 Label* is_instance_lbl,
268 Label* is_not_instance_lbl) { 272 Label* is_not_instance_lbl) {
269 __ Comment("InstantiatedTypeWithArgumentsTest"); 273 __ Comment("InstantiatedTypeWithArgumentsTest");
270 ASSERT(type.IsInstantiated()); 274 ASSERT(type.IsInstantiated());
271 const Class& type_class = Class::ZoneHandle(type.type_class()); 275 const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
272 ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass()); 276 ASSERT((type_class.NumTypeArguments() > 0) || type_class.IsSignatureClass());
273 const Register kInstanceReg = EAX; 277 const Register kInstanceReg = EAX;
274 Error& malformed_error = Error::Handle(); 278 Error& malformed_error = Error::Handle(zone());
275 const Type& int_type = Type::Handle(Type::IntType()); 279 const Type& int_type = Type::Handle(zone(), Type::IntType());
276 const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error); 280 const bool smi_is_ok = int_type.IsSubtypeOf(type, &malformed_error);
277 // Malformed type should have been handled at graph construction time. 281 // Malformed type should have been handled at graph construction time.
278 ASSERT(smi_is_ok || malformed_error.IsNull()); 282 ASSERT(smi_is_ok || malformed_error.IsNull());
279 __ testl(kInstanceReg, Immediate(kSmiTagMask)); 283 __ testl(kInstanceReg, Immediate(kSmiTagMask));
280 if (smi_is_ok) { 284 if (smi_is_ok) {
281 __ j(ZERO, is_instance_lbl); 285 __ j(ZERO, is_instance_lbl);
282 } else { 286 } else {
283 __ j(ZERO, is_not_instance_lbl); 287 __ j(ZERO, is_not_instance_lbl);
284 } 288 }
285 const intptr_t num_type_args = type_class.NumTypeArguments(); 289 const intptr_t num_type_args = type_class.NumTypeArguments();
286 const intptr_t num_type_params = type_class.NumTypeParameters(); 290 const intptr_t num_type_params = type_class.NumTypeParameters();
287 const intptr_t from_index = num_type_args - num_type_params; 291 const intptr_t from_index = num_type_args - num_type_params;
288 const TypeArguments& type_arguments = 292 const TypeArguments& type_arguments =
289 TypeArguments::ZoneHandle(type.arguments()); 293 TypeArguments::ZoneHandle(zone(), type.arguments());
290 const bool is_raw_type = type_arguments.IsNull() || 294 const bool is_raw_type = type_arguments.IsNull() ||
291 type_arguments.IsRaw(from_index, num_type_params); 295 type_arguments.IsRaw(from_index, num_type_params);
292 // Signature class is an instantiated parameterized type. 296 // Signature class is an instantiated parameterized type.
293 if (!type_class.IsSignatureClass()) { 297 if (!type_class.IsSignatureClass()) {
294 if (is_raw_type) { 298 if (is_raw_type) {
295 const Register kClassIdReg = ECX; 299 const Register kClassIdReg = ECX;
296 // dynamic type argument, check only classes. 300 // dynamic type argument, check only classes.
297 __ LoadClassId(kClassIdReg, kInstanceReg); 301 __ LoadClassId(kClassIdReg, kInstanceReg);
298 __ cmpl(kClassIdReg, Immediate(type_class.id())); 302 __ cmpl(kClassIdReg, Immediate(type_class.id()));
299 __ j(EQUAL, is_instance_lbl); 303 __ j(EQUAL, is_instance_lbl);
300 // List is a very common case. 304 // List is a very common case.
301 if (IsListClass(type_class)) { 305 if (IsListClass(type_class)) {
302 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); 306 GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
303 } 307 }
304 return GenerateSubtype1TestCacheLookup( 308 return GenerateSubtype1TestCacheLookup(
305 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 309 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
306 } 310 }
307 // If one type argument only, check if type argument is Object or dynamic. 311 // If one type argument only, check if type argument is Object or dynamic.
308 if (type_arguments.Length() == 1) { 312 if (type_arguments.Length() == 1) {
309 const AbstractType& tp_argument = AbstractType::ZoneHandle( 313 const AbstractType& tp_argument = AbstractType::ZoneHandle(
310 type_arguments.TypeAt(0)); 314 zone(), type_arguments.TypeAt(0));
311 ASSERT(!tp_argument.IsMalformed()); 315 ASSERT(!tp_argument.IsMalformed());
312 if (tp_argument.IsType()) { 316 if (tp_argument.IsType()) {
313 ASSERT(tp_argument.HasResolvedTypeClass()); 317 ASSERT(tp_argument.HasResolvedTypeClass());
314 // Check if type argument is dynamic or Object. 318 // Check if type argument is dynamic or Object.
315 const Type& object_type = Type::Handle(Type::ObjectType()); 319 const Type& object_type = Type::Handle(zone(), Type::ObjectType());
316 if (object_type.IsSubtypeOf(tp_argument, NULL)) { 320 if (object_type.IsSubtypeOf(tp_argument, NULL)) {
317 // Instance class test only necessary. 321 // Instance class test only necessary.
318 return GenerateSubtype1TestCacheLookup( 322 return GenerateSubtype1TestCacheLookup(
319 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 323 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
320 } 324 }
321 } 325 }
322 } 326 }
323 } 327 }
324 // Regular subtype test cache involving instance's type arguments. 328 // Regular subtype test cache involving instance's type arguments.
325 const Register kTypeArgumentsReg = kNoRegister; 329 const Register kTypeArgumentsReg = kNoRegister;
(...skipping 24 matching lines...) Expand all
350 // EAX: instance to test against (preserved). 354 // EAX: instance to test against (preserved).
351 // Clobbers ECX, EDI. 355 // Clobbers ECX, EDI.
352 // Returns true if there is a fallthrough. 356 // Returns true if there is a fallthrough.
353 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 357 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
354 intptr_t token_pos, 358 intptr_t token_pos,
355 const AbstractType& type, 359 const AbstractType& type,
356 Label* is_instance_lbl, 360 Label* is_instance_lbl,
357 Label* is_not_instance_lbl) { 361 Label* is_not_instance_lbl) {
358 __ Comment("InstantiatedTypeNoArgumentsTest"); 362 __ Comment("InstantiatedTypeNoArgumentsTest");
359 ASSERT(type.IsInstantiated()); 363 ASSERT(type.IsInstantiated());
360 const Class& type_class = Class::Handle(type.type_class()); 364 const Class& type_class = Class::Handle(zone(), type.type_class());
361 ASSERT(type_class.NumTypeArguments() == 0); 365 ASSERT(type_class.NumTypeArguments() == 0);
362 366
363 const Register kInstanceReg = EAX; 367 const Register kInstanceReg = EAX;
364 __ testl(kInstanceReg, Immediate(kSmiTagMask)); 368 __ testl(kInstanceReg, Immediate(kSmiTagMask));
365 // If instance is Smi, check directly. 369 // If instance is Smi, check directly.
366 const Class& smi_class = Class::Handle(Smi::Class()); 370 const Class& smi_class = Class::Handle(zone(), Smi::Class());
367 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 371 if (smi_class.IsSubtypeOf(TypeArguments::Handle(zone()),
368 type_class, 372 type_class,
369 TypeArguments::Handle(), 373 TypeArguments::Handle(zone()),
370 NULL)) { 374 NULL)) {
371 __ j(ZERO, is_instance_lbl); 375 __ j(ZERO, is_instance_lbl);
372 } else { 376 } else {
373 __ j(ZERO, is_not_instance_lbl); 377 __ j(ZERO, is_not_instance_lbl);
374 } 378 }
375 // Compare if the classes are equal. 379 // Compare if the classes are equal.
376 const Register kClassIdReg = ECX; 380 const Register kClassIdReg = ECX;
377 __ LoadClassId(kClassIdReg, kInstanceReg); 381 __ LoadClassId(kClassIdReg, kInstanceReg);
378 __ cmpl(kClassIdReg, Immediate(type_class.id())); 382 __ cmpl(kClassIdReg, Immediate(type_class.id()));
379 __ j(EQUAL, is_instance_lbl); 383 __ j(EQUAL, is_instance_lbl);
(...skipping 10 matching lines...) Expand all
390 // Check if instance is a closure. 394 // Check if instance is a closure.
391 const Immediate& raw_null = 395 const Immediate& raw_null =
392 Immediate(reinterpret_cast<intptr_t>(Object::null())); 396 Immediate(reinterpret_cast<intptr_t>(Object::null()));
393 __ LoadClassById(EDI, kClassIdReg); 397 __ LoadClassById(EDI, kClassIdReg);
394 __ movl(EDI, FieldAddress(EDI, Class::signature_function_offset())); 398 __ movl(EDI, FieldAddress(EDI, Class::signature_function_offset()));
395 __ cmpl(EDI, raw_null); 399 __ cmpl(EDI, raw_null);
396 __ j(NOT_EQUAL, is_instance_lbl); 400 __ j(NOT_EQUAL, is_instance_lbl);
397 } 401 }
398 // Custom checking for numbers (Smi, Mint, Bigint and Double). 402 // Custom checking for numbers (Smi, Mint, Bigint and Double).
399 // Note that instance is not Smi (checked above). 403 // Note that instance is not Smi (checked above).
400 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) { 404 if (type.IsSubtypeOf(Type::Handle(zone(), Type::Number()), NULL)) {
401 GenerateNumberTypeCheck( 405 GenerateNumberTypeCheck(
402 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl); 406 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
403 return false; 407 return false;
404 } 408 }
405 if (type.IsStringType()) { 409 if (type.IsStringType()) {
406 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 410 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
407 return false; 411 return false;
408 } 412 }
409 // Otherwise fallthrough. 413 // Otherwise fallthrough.
410 return true; 414 return true;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 // Load instantiator (or null) and instantiator type arguments on stack. 466 // Load instantiator (or null) and instantiator type arguments on stack.
463 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 467 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
464 // EDX: instantiator type arguments. 468 // EDX: instantiator type arguments.
465 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 469 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
466 __ cmpl(EDX, raw_null); 470 __ cmpl(EDX, raw_null);
467 __ j(EQUAL, is_instance_lbl); 471 __ j(EQUAL, is_instance_lbl);
468 __ movl(EDI, 472 __ movl(EDI,
469 FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index()))); 473 FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index())));
470 // EDI: concrete type of type. 474 // EDI: concrete type of type.
471 // Check if type argument is dynamic. 475 // Check if type argument is dynamic.
472 __ CompareObject(EDI, Type::ZoneHandle(Type::DynamicType())); 476 __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::DynamicType()));
473 __ j(EQUAL, is_instance_lbl); 477 __ j(EQUAL, is_instance_lbl);
474 __ CompareObject(EDI, Type::ZoneHandle(Type::ObjectType())); 478 __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::ObjectType()));
475 __ j(EQUAL, is_instance_lbl); 479 __ j(EQUAL, is_instance_lbl);
476 480
477 // For Smi check quickly against int and num interfaces. 481 // For Smi check quickly against int and num interfaces.
478 Label not_smi; 482 Label not_smi;
479 __ testl(EAX, Immediate(kSmiTagMask)); // Value is Smi? 483 __ testl(EAX, Immediate(kSmiTagMask)); // Value is Smi?
480 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump); 484 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
481 __ CompareObject(EDI, Type::ZoneHandle(Type::IntType())); 485 __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::IntType()));
482 __ j(EQUAL, is_instance_lbl); 486 __ j(EQUAL, is_instance_lbl);
483 __ CompareObject(EDI, Type::ZoneHandle(Type::Number())); 487 __ CompareObject(EDI, Type::ZoneHandle(zone(), Type::Number()));
484 __ j(EQUAL, is_instance_lbl); 488 __ j(EQUAL, is_instance_lbl);
485 // Smi must be handled in runtime. 489 // Smi must be handled in runtime.
486 Label fall_through; 490 Label fall_through;
487 __ jmp(&fall_through); 491 __ jmp(&fall_through);
488 492
489 __ Bind(&not_smi); 493 __ Bind(&not_smi);
490 // EDX: instantiator type arguments. 494 // EDX: instantiator type arguments.
491 // EAX: instance. 495 // EAX: instance.
492 const Register kInstanceReg = EAX; 496 const Register kInstanceReg = EAX;
493 const Register kTypeArgumentsReg = EDX; 497 const Register kTypeArgumentsReg = EDX;
494 const Register kTempReg = EDI; 498 const Register kTempReg = EDI;
495 const SubtypeTestCache& type_test_cache = 499 const SubtypeTestCache& type_test_cache =
496 SubtypeTestCache::ZoneHandle( 500 SubtypeTestCache::ZoneHandle(zone(),
497 GenerateCallSubtypeTestStub(kTestTypeThreeArgs, 501 GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
498 kInstanceReg, 502 kInstanceReg,
499 kTypeArgumentsReg, 503 kTypeArgumentsReg,
500 kTempReg, 504 kTempReg,
501 is_instance_lbl, 505 is_instance_lbl,
502 is_not_instance_lbl)); 506 is_not_instance_lbl));
503 __ Bind(&fall_through); 507 __ Bind(&fall_through);
504 return type_test_cache.raw(); 508 return type_test_cache.raw();
505 } 509 }
506 if (type.IsType()) { 510 if (type.IsType()) {
(...skipping 30 matching lines...) Expand all
537 const AbstractType& type, 541 const AbstractType& type,
538 Label* is_instance_lbl, 542 Label* is_instance_lbl,
539 Label* is_not_instance_lbl) { 543 Label* is_not_instance_lbl) {
540 __ Comment("InlineInstanceof"); 544 __ Comment("InlineInstanceof");
541 if (type.IsVoidType()) { 545 if (type.IsVoidType()) {
542 // A non-null value is returned from a void function, which will result in a 546 // A non-null value is returned from a void function, which will result in a
543 // type error. A null value is handled prior to executing this inline code. 547 // type error. A null value is handled prior to executing this inline code.
544 return SubtypeTestCache::null(); 548 return SubtypeTestCache::null();
545 } 549 }
546 if (type.IsInstantiated()) { 550 if (type.IsInstantiated()) {
547 const Class& type_class = Class::ZoneHandle(type.type_class()); 551 const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
548 // A class equality check is only applicable with a dst type of a 552 // A class equality check is only applicable with a dst type of a
549 // non-parameterized class, non-signature class, or with a raw dst type of 553 // non-parameterized class, non-signature class, or with a raw dst type of
550 // a parameterized class. 554 // a parameterized class.
551 if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) { 555 if (type_class.IsSignatureClass() || (type_class.NumTypeArguments() > 0)) {
552 return GenerateInstantiatedTypeWithArgumentsTest(token_pos, 556 return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
553 type, 557 type,
554 is_instance_lbl, 558 is_instance_lbl,
555 is_not_instance_lbl); 559 is_not_instance_lbl);
556 // Fall through to runtime call. 560 // Fall through to runtime call.
557 } 561 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 // return false here if the instance is null (and if the type is 612 // return false here if the instance is null (and if the type is
609 // instantiated). 613 // instantiated).
610 // We can only inline this null check if the type is instantiated at compile 614 // We can only inline this null check if the type is instantiated at compile
611 // time, since an uninstantiated type at compile time could be Object or 615 // time, since an uninstantiated type at compile time could be Object or
612 // dynamic at run time. 616 // dynamic at run time.
613 __ cmpl(EAX, raw_null); 617 __ cmpl(EAX, raw_null);
614 __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance); 618 __ j(EQUAL, type.IsNullType() ? &is_instance : &is_not_instance);
615 } 619 }
616 620
617 // Generate inline instanceof test. 621 // Generate inline instanceof test.
618 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 622 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
619 test_cache = GenerateInlineInstanceof(token_pos, type, 623 test_cache = GenerateInlineInstanceof(token_pos, type,
620 &is_instance, &is_not_instance); 624 &is_instance, &is_not_instance);
621 625
622 // test_cache is null if there is no fall-through. 626 // test_cache is null if there is no fall-through.
623 Label done; 627 Label done;
624 if (!test_cache.IsNull()) { 628 if (!test_cache.IsNull()) {
625 // Generate runtime call. 629 // Generate runtime call.
626 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 630 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
627 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 631 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
628 __ PushObject(Object::null_object()); // Make room for the result. 632 __ PushObject(Object::null_object()); // Make room for the result.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
709 // We should never return here. 713 // We should never return here.
710 __ int3(); 714 __ int3();
711 715
712 __ Bind(&is_assignable); // For a null object. 716 __ Bind(&is_assignable); // For a null object.
713 __ popl(EDX); // Remove pushed instantiator type arguments. 717 __ popl(EDX); // Remove pushed instantiator type arguments.
714 __ popl(ECX); // Remove pushed instantiator. 718 __ popl(ECX); // Remove pushed instantiator.
715 return; 719 return;
716 } 720 }
717 721
718 // Generate inline type check, linking to runtime call if not assignable. 722 // Generate inline type check, linking to runtime call if not assignable.
719 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 723 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
720 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 724 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
721 &is_assignable, &runtime_call); 725 &is_assignable, &runtime_call);
722 726
723 __ Bind(&runtime_call); 727 __ Bind(&runtime_call);
724 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 728 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
725 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 729 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
726 __ PushObject(Object::null_object()); // Make room for the result. 730 __ PushObject(Object::null_object()); // Make room for the result.
727 __ pushl(EAX); // Push the source object. 731 __ pushl(EAX); // Push the source object.
728 __ PushObject(dst_type); // Push the type of the destination. 732 __ PushObject(dst_type); // Push the type of the destination.
729 __ pushl(ECX); // Instantiator. 733 __ pushl(ECX); // Instantiator.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 __ movl(EAX, Address(EDI, ArgumentsDescriptor::position_offset())); 877 __ movl(EAX, Address(EDI, ArgumentsDescriptor::position_offset()));
874 // EAX is arg_pos as Smi. 878 // EAX is arg_pos as Smi.
875 // Point to next named entry. 879 // Point to next named entry.
876 __ addl(EDI, Immediate(ArgumentsDescriptor::named_entry_size())); 880 __ addl(EDI, Immediate(ArgumentsDescriptor::named_entry_size()));
877 __ negl(EAX); 881 __ negl(EAX);
878 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi. 882 Address argument_addr(EBX, EAX, TIMES_2, 0); // EAX is a negative Smi.
879 __ movl(EAX, argument_addr); 883 __ movl(EAX, argument_addr);
880 __ jmp(&assign_optional_parameter, Assembler::kNearJump); 884 __ jmp(&assign_optional_parameter, Assembler::kNearJump);
881 __ Bind(&load_default_value); 885 __ Bind(&load_default_value);
882 // Load EAX with default argument. 886 // Load EAX with default argument.
883 const Object& value = Object::ZoneHandle( 887 const Object& value = Object::ZoneHandle(zone(),
884 parsed_function().default_parameter_values().At( 888 parsed_function().default_parameter_values().At(
885 param_pos - num_fixed_params)); 889 param_pos - num_fixed_params));
886 __ LoadObject(EAX, value); 890 __ LoadObject(EAX, value);
887 __ Bind(&assign_optional_parameter); 891 __ Bind(&assign_optional_parameter);
888 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. 892 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos].
889 // We do not use the final allocation index of the variable here, i.e. 893 // We do not use the final allocation index of the variable here, i.e.
890 // scope->VariableAt(i)->index(), because captured variables still need 894 // scope->VariableAt(i)->index(), because captured variables still need
891 // to be copied to the context that is not yet allocated. 895 // to be copied to the context that is not yet allocated.
892 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 896 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
893 const Address param_addr(EBP, computed_param_pos * kWordSize); 897 const Address param_addr(EBP, computed_param_pos * kWordSize);
(...skipping 14 matching lines...) Expand all
908 __ SmiUntag(ECX); 912 __ SmiUntag(ECX);
909 for (int i = 0; i < num_opt_pos_params; i++) { 913 for (int i = 0; i < num_opt_pos_params; i++) {
910 Label next_parameter; 914 Label next_parameter;
911 // Handle this optional positional parameter only if k or fewer positional 915 // Handle this optional positional parameter only if k or fewer positional
912 // arguments have been passed, where k is param_pos, the position of this 916 // arguments have been passed, where k is param_pos, the position of this
913 // optional parameter in the formal parameter list. 917 // optional parameter in the formal parameter list.
914 const int param_pos = num_fixed_params + i; 918 const int param_pos = num_fixed_params + i;
915 __ cmpl(ECX, Immediate(param_pos)); 919 __ cmpl(ECX, Immediate(param_pos));
916 __ j(GREATER, &next_parameter, Assembler::kNearJump); 920 __ j(GREATER, &next_parameter, Assembler::kNearJump);
917 // Load EAX with default argument. 921 // Load EAX with default argument.
918 const Object& value = Object::ZoneHandle( 922 const Object& value = Object::ZoneHandle(zone(),
919 parsed_function().default_parameter_values().At(i)); 923 parsed_function().default_parameter_values().At(i));
920 __ LoadObject(EAX, value); 924 __ LoadObject(EAX, value);
921 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos]. 925 // Assign EAX to fp[kFirstLocalSlotFromFp - param_pos].
922 // We do not use the final allocation index of the variable here, i.e. 926 // We do not use the final allocation index of the variable here, i.e.
923 // scope->VariableAt(i)->index(), because captured variables still need 927 // scope->VariableAt(i)->index(), because captured variables still need
924 // to be copied to the context that is not yet allocated. 928 // to be copied to the context that is not yet allocated.
925 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 929 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
926 const Address param_addr(EBP, computed_param_pos * kWordSize); 930 const Address param_addr(EBP, computed_param_pos * kWordSize);
927 __ movl(param_addr, EAX); 931 __ movl(param_addr, EAX);
928 __ Bind(&next_parameter); 932 __ Bind(&next_parameter);
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 __ Drop(argument_count); 1226 __ Drop(argument_count);
1223 } 1227 }
1224 1228
1225 1229
1226 void FlowGraphCompiler::EmitEdgeCounter() { 1230 void FlowGraphCompiler::EmitEdgeCounter() {
1227 // We do not check for overflow when incrementing the edge counter. The 1231 // We do not check for overflow when incrementing the edge counter. The
1228 // function should normally be optimized long before the counter can 1232 // function should normally be optimized long before the counter can
1229 // overflow; and though we do not reset the counters when we optimize or 1233 // overflow; and though we do not reset the counters when we optimize or
1230 // deoptimize, there is a bound on the number of 1234 // deoptimize, there is a bound on the number of
1231 // optimization/deoptimization cycles we will attempt. 1235 // optimization/deoptimization cycles we will attempt.
1232 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); 1236 const Array& counter = Array::ZoneHandle(zone(), Array::New(1, Heap::kOld));
1233 counter.SetAt(0, Smi::Handle(Smi::New(0))); 1237 counter.SetAt(0, Smi::Handle(zone(), Smi::New(0)));
1234 __ Comment("Edge counter"); 1238 __ Comment("Edge counter");
1235 __ LoadObject(EAX, counter); 1239 __ LoadObject(EAX, counter);
1236 intptr_t increment_start = assembler_->CodeSize(); 1240 intptr_t increment_start = assembler_->CodeSize();
1237 __ IncrementSmiField(FieldAddress(EAX, Array::element_offset(0)), 1); 1241 __ IncrementSmiField(FieldAddress(EAX, Array::element_offset(0)), 1);
1238 int32_t size = assembler_->CodeSize() - increment_start; 1242 int32_t size = assembler_->CodeSize() - increment_start;
1239 if (isolate()->edge_counter_increment_size() == -1) { 1243 if (isolate()->edge_counter_increment_size() == -1) {
1240 isolate()->set_edge_counter_increment_size(size); 1244 isolate()->set_edge_counter_increment_size(size);
1241 } else { 1245 } else {
1242 ASSERT(size == isolate()->edge_counter_increment_size()); 1246 ASSERT(size == isolate()->edge_counter_increment_size());
1243 } 1247 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 } 1297 }
1294 1298
1295 1299
1296 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1300 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
1297 const ICData& ic_data, 1301 const ICData& ic_data,
1298 intptr_t argument_count, 1302 intptr_t argument_count,
1299 intptr_t deopt_id, 1303 intptr_t deopt_id,
1300 intptr_t token_pos, 1304 intptr_t token_pos,
1301 LocationSummary* locs) { 1305 LocationSummary* locs) {
1302 MegamorphicCacheTable* table = isolate()->megamorphic_cache_table(); 1306 MegamorphicCacheTable* table = isolate()->megamorphic_cache_table();
1303 const String& name = String::Handle(ic_data.target_name()); 1307 const String& name = String::Handle(zone(), ic_data.target_name());
1304 const Array& arguments_descriptor = 1308 const Array& arguments_descriptor =
1305 Array::ZoneHandle(ic_data.arguments_descriptor()); 1309 Array::ZoneHandle(zone(), ic_data.arguments_descriptor());
1306 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); 1310 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0));
1307 const MegamorphicCache& cache = 1311 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(),
1308 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); 1312 table->Lookup(name, arguments_descriptor));
1309 const Register receiverR = EDI; 1313 const Register receiverR = EDI;
1310 const Register cacheR = EBX; 1314 const Register cacheR = EBX;
1311 const Register targetR = EBX; 1315 const Register targetR = EBX;
1312 __ movl(receiverR, Address(ESP, (argument_count - 1) * kWordSize)); 1316 __ movl(receiverR, Address(ESP, (argument_count - 1) * kWordSize));
1313 __ LoadObject(cacheR, cache); 1317 __ LoadObject(cacheR, cache);
1314 1318
1315 if (FLAG_use_megamorphic_stub) { 1319 if (FLAG_use_megamorphic_stub) {
1316 __ call(&StubCode::MegamorphicLookupLabel()); 1320 __ call(&StubCode::MegamorphicLookupLabel());
1317 } else { 1321 } else {
1318 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); 1322 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 intptr_t argument_count, 1507 intptr_t argument_count,
1504 const Array& argument_names, 1508 const Array& argument_names,
1505 Label* failed, 1509 Label* failed,
1506 Label* match_found, 1510 Label* match_found,
1507 intptr_t deopt_id, 1511 intptr_t deopt_id,
1508 intptr_t token_index, 1512 intptr_t token_index,
1509 LocationSummary* locs) { 1513 LocationSummary* locs) {
1510 ASSERT(is_optimizing()); 1514 ASSERT(is_optimizing());
1511 __ Comment("EmitTestAndCall"); 1515 __ Comment("EmitTestAndCall");
1512 const Array& arguments_descriptor = 1516 const Array& arguments_descriptor =
1513 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, 1517 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count,
1514 argument_names)); 1518 argument_names));
1515 // Load receiver into EAX. 1519 // Load receiver into EAX.
1516 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize)); 1520 __ movl(EAX, Address(ESP, (argument_count - 1) * kWordSize));
1517 __ LoadObject(EDX, arguments_descriptor); 1521 __ LoadObject(EDX, arguments_descriptor);
1518 1522
1519 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; 1523 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid;
1520 const intptr_t kNumChecks = ic_data.NumberOfChecks(); 1524 const intptr_t kNumChecks = ic_data.NumberOfChecks();
1521 1525
1522 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); 1526 ASSERT(!ic_data.IsNull() && (kNumChecks > 0));
1523 1527
1524 Label after_smi_test; 1528 Label after_smi_test;
1525 __ testl(EAX, Immediate(kSmiTagMask)); 1529 __ testl(EAX, Immediate(kSmiTagMask));
1526 if (kFirstCheckIsSmi) { 1530 if (kFirstCheckIsSmi) {
1527 // Jump if receiver is not Smi. 1531 // Jump if receiver is not Smi.
1528 if (kNumChecks == 1) { 1532 if (kNumChecks == 1) {
1529 __ j(NOT_ZERO, failed); 1533 __ j(NOT_ZERO, failed);
1530 } else { 1534 } else {
1531 __ j(NOT_ZERO, &after_smi_test); 1535 __ j(NOT_ZERO, &after_smi_test);
1532 } 1536 }
1533 // Do not use the code from the function, but let the code be patched so 1537 // Do not use the code from the function, but let the code be patched so
1534 // that we can record the outgoing edges to other code. 1538 // that we can record the outgoing edges to other code.
1535 GenerateDartCall(deopt_id, 1539 GenerateDartCall(deopt_id,
1536 token_index, 1540 token_index,
1537 &StubCode::CallStaticFunctionLabel(), 1541 &StubCode::CallStaticFunctionLabel(),
1538 RawPcDescriptors::kOther, 1542 RawPcDescriptors::kOther,
1539 locs); 1543 locs);
1540 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); 1544 const Function& function = Function::Handle(zone(), ic_data.GetTargetAt(0));
1541 AddStaticCallTarget(function); 1545 AddStaticCallTarget(function);
1542 __ Drop(argument_count); 1546 __ Drop(argument_count);
1543 if (kNumChecks > 1) { 1547 if (kNumChecks > 1) {
1544 __ jmp(match_found); 1548 __ jmp(match_found);
1545 } 1549 }
1546 } else { 1550 } else {
1547 // Receiver is Smi, but Smi is not a valid class therefore fail. 1551 // Receiver is Smi, but Smi is not a valid class therefore fail.
1548 // (Smi class must be first in the list). 1552 // (Smi class must be first in the list).
1549 __ j(ZERO, failed); 1553 __ j(ZERO, failed);
1550 } 1554 }
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1850 __ movups(reg, Address(ESP, 0)); 1854 __ movups(reg, Address(ESP, 0));
1851 __ addl(ESP, Immediate(kFpuRegisterSize)); 1855 __ addl(ESP, Immediate(kFpuRegisterSize));
1852 } 1856 }
1853 1857
1854 1858
1855 #undef __ 1859 #undef __
1856 1860
1857 } // namespace dart 1861 } // namespace dart
1858 1862
1859 #endif // defined TARGET_ARCH_IA32 1863 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_arm64.cc ('k') | runtime/vm/flow_graph_compiler_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698