| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 __ Bind(¬_yet_hot); | 81 __ Bind(¬_yet_hot); |
| 82 __ Bind(&already_optimized); | 82 __ Bind(&already_optimized); |
| 83 } | 83 } |
| 84 } | 84 } |
| 85 if (FLAG_trace_functions) { | 85 if (FLAG_trace_functions) { |
| 86 const Function& function = | 86 const Function& function = |
| 87 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 87 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
| 88 __ LoadObject(temp, function); | 88 __ LoadObject(temp, function); |
| 89 __ pushl(result); // Preserve result. | 89 __ pushl(result); // Preserve result. |
| 90 __ pushl(temp); | 90 __ pushl(temp); |
| 91 compiler->GenerateCallRuntime(AstNode::kNoId, | 91 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
| 92 0, | 92 0, |
| 93 CatchClauseNode::kInvalidTryIndex, | 93 CatchClauseNode::kInvalidTryIndex, |
| 94 kTraceFunctionExitRuntimeEntry); | 94 kTraceFunctionExitRuntimeEntry); |
| 95 __ popl(temp); // Remove argument. | 95 __ popl(temp); // Remove argument. |
| 96 __ popl(result); // Restore result. | 96 __ popl(result); // Restore result. |
| 97 } | 97 } |
| 98 __ LeaveFrame(); | 98 __ LeaveFrame(); |
| 99 __ ret(); | 99 __ ret(); |
| 100 | 100 |
| 101 // Generate 1 byte NOP so that the debugger can patch the | 101 // Generate 1 byte NOP so that the debugger can patch the |
| 102 // return pattern with a call to the debug stub. | 102 // return pattern with a call to the debug stub. |
| 103 __ nop(1); | 103 __ nop(1); |
| 104 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 104 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 105 cid(), | 105 deopt_id(), |
| 106 token_pos(), | 106 token_pos(), |
| 107 CatchClauseNode::kInvalidTryIndex); | 107 CatchClauseNode::kInvalidTryIndex); |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 111 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 112 const intptr_t kNumInputs = 0; | 112 const intptr_t kNumInputs = 0; |
| 113 const intptr_t kNumTemps = 1; | 113 const intptr_t kNumTemps = 1; |
| 114 LocationSummary* result = | 114 LocationSummary* result = |
| 115 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 115 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 | 190 |
| 191 // Check that the type of the value is allowed in conditional context. | 191 // Check that the type of the value is allowed in conditional context. |
| 192 // Call the runtime if the object is not bool::true or bool::false. | 192 // Call the runtime if the object is not bool::true or bool::false. |
| 193 Label done; | 193 Label done; |
| 194 __ CompareObject(obj, compiler->bool_true()); | 194 __ CompareObject(obj, compiler->bool_true()); |
| 195 __ j(EQUAL, &done, Assembler::kNearJump); | 195 __ j(EQUAL, &done, Assembler::kNearJump); |
| 196 __ CompareObject(obj, compiler->bool_false()); | 196 __ CompareObject(obj, compiler->bool_false()); |
| 197 __ j(EQUAL, &done, Assembler::kNearJump); | 197 __ j(EQUAL, &done, Assembler::kNearJump); |
| 198 | 198 |
| 199 __ pushl(obj); // Push the source object. | 199 __ pushl(obj); // Push the source object. |
| 200 compiler->GenerateCallRuntime(cid(), | 200 compiler->GenerateCallRuntime(deopt_id(), |
| 201 token_pos(), | 201 token_pos(), |
| 202 try_index(), | 202 try_index(), |
| 203 kConditionTypeErrorRuntimeEntry); | 203 kConditionTypeErrorRuntimeEntry); |
| 204 // We should never return here. | 204 // We should never return here. |
| 205 __ int3(); | 205 __ int3(); |
| 206 | 206 |
| 207 __ Bind(&done); | 207 __ Bind(&done); |
| 208 ASSERT(obj == result); | 208 ASSERT(obj == result); |
| 209 } | 209 } |
| 210 | 210 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 } | 257 } |
| 258 | 258 |
| 259 | 259 |
| 260 // Optional integer arguments can often be null. Null is not collected | 260 // Optional integer arguments can often be null. Null is not collected |
| 261 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? | 261 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? |
| 262 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 262 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| 263 EqualityCompareComp* comp) { | 263 EqualityCompareComp* comp) { |
| 264 Register left = comp->locs()->in(0).reg(); | 264 Register left = comp->locs()->in(0).reg(); |
| 265 Register right = comp->locs()->in(1).reg(); | 265 Register right = comp->locs()->in(1).reg(); |
| 266 Register temp = comp->locs()->temp(0).reg(); | 266 Register temp = comp->locs()->temp(0).reg(); |
| 267 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 267 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 268 comp->token_pos(), | 268 comp->token_pos(), |
| 269 comp->try_index(), | 269 comp->try_index(), |
| 270 kDeoptSmiCompareSmi, | 270 kDeoptSmiCompareSmi, |
| 271 left, | 271 left, |
| 272 right); | 272 right); |
| 273 __ movl(temp, left); | 273 __ movl(temp, left); |
| 274 __ orl(temp, right); | 274 __ orl(temp, right); |
| 275 __ testl(temp, Immediate(kSmiTagMask)); | 275 __ testl(temp, Immediate(kSmiTagMask)); |
| 276 __ j(NOT_ZERO, deopt); | 276 __ j(NOT_ZERO, deopt); |
| 277 __ cmpl(left, right); | 277 __ cmpl(left, right); |
| 278 Register result = comp->locs()->out().reg(); | 278 Register result = comp->locs()->out().reg(); |
| 279 Label load_true, done; | 279 Label load_true, done; |
| 280 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump); | 280 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump); |
| 281 __ LoadObject(result, compiler->bool_false()); | 281 __ LoadObject(result, compiler->bool_false()); |
| 282 __ jmp(&done, Assembler::kNearJump); | 282 __ jmp(&done, Assembler::kNearJump); |
| 283 __ Bind(&load_true); | 283 __ Bind(&load_true); |
| 284 __ LoadObject(result, compiler->bool_true()); | 284 __ LoadObject(result, compiler->bool_true()); |
| 285 __ Bind(&done); | 285 __ Bind(&done); |
| 286 } | 286 } |
| 287 | 287 |
| 288 | 288 |
| 289 // TODO(srdjan): Add support for mixed Smi/Double equality | 289 // TODO(srdjan): Add support for mixed Smi/Double equality |
| 290 // (see LoadDoubleOrSmiToXmm). | 290 // (see LoadDoubleOrSmiToXmm). |
| 291 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, | 291 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, |
| 292 EqualityCompareComp* comp) { | 292 EqualityCompareComp* comp) { |
| 293 Register left = comp->locs()->in(0).reg(); | 293 Register left = comp->locs()->in(0).reg(); |
| 294 Register right = comp->locs()->in(1).reg(); | 294 Register right = comp->locs()->in(1).reg(); |
| 295 Register temp = comp->locs()->temp(0).reg(); | 295 Register temp = comp->locs()->temp(0).reg(); |
| 296 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 296 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 297 comp->token_pos(), | 297 comp->token_pos(), |
| 298 comp->try_index(), | 298 comp->try_index(), |
| 299 kDeoptDoubleCompareDouble, | 299 kDeoptDoubleCompareDouble, |
| 300 left, | 300 left, |
| 301 right); | 301 right); |
| 302 Label done, is_false, is_true; | 302 Label done, is_false, is_true; |
| 303 __ CompareClassId(left, kDouble, temp); | 303 __ CompareClassId(left, kDouble, temp); |
| 304 __ j(NOT_EQUAL, deopt); | 304 __ j(NOT_EQUAL, deopt); |
| 305 __ CompareClassId(right, kDouble, temp); | 305 __ CompareClassId(right, kDouble, temp); |
| 306 __ j(NOT_EQUAL, deopt); | 306 __ j(NOT_EQUAL, deopt); |
| 307 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); | 307 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); |
| 308 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); | 308 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); |
| 309 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()), | 309 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()), |
| 310 XMM0, XMM1, | 310 XMM0, XMM1, |
| 311 comp->locs()->out().reg()); | 311 comp->locs()->out().reg()); |
| 312 } | 312 } |
| 313 | 313 |
| 314 | 314 |
| 315 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 315 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 316 EqualityCompareComp* comp) { | 316 EqualityCompareComp* comp) { |
| 317 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 317 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 318 comp->cid(), | 318 comp->deopt_id(), |
| 319 comp->token_pos(), | 319 comp->token_pos(), |
| 320 comp->try_index()); | 320 comp->try_index()); |
| 321 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 321 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 322 const int kNumberOfArguments = 2; | 322 const int kNumberOfArguments = 2; |
| 323 const Array& kNoArgumentNames = Array::Handle(); | 323 const Array& kNoArgumentNames = Array::Handle(); |
| 324 const int kNumArgumentsChecked = 2; | 324 const int kNumArgumentsChecked = 2; |
| 325 | 325 |
| 326 compiler->GenerateInstanceCall(comp->cid(), | 326 compiler->GenerateInstanceCall(comp->deopt_id(), |
| 327 comp->token_pos(), | 327 comp->token_pos(), |
| 328 comp->try_index(), | 328 comp->try_index(), |
| 329 operator_name, | 329 operator_name, |
| 330 kNumberOfArguments, | 330 kNumberOfArguments, |
| 331 kNoArgumentNames, | 331 kNoArgumentNames, |
| 332 kNumArgumentsChecked); | 332 kNumArgumentsChecked); |
| 333 ASSERT(comp->locs()->out().reg() == EAX); | 333 ASSERT(comp->locs()->out().reg() == EAX); |
| 334 if (comp->kind() == Token::kNE) { | 334 if (comp->kind() == Token::kNE) { |
| 335 Label done, false_label; | 335 Label done, false_label; |
| 336 __ CompareObject(EAX, compiler->bool_true()); | 336 __ CompareObject(EAX, compiler->bool_true()); |
| 337 __ j(EQUAL, &false_label, Assembler::kNearJump); | 337 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| 338 __ LoadObject(EAX, compiler->bool_true()); | 338 __ LoadObject(EAX, compiler->bool_true()); |
| 339 __ jmp(&done, Assembler::kNearJump); | 339 __ jmp(&done, Assembler::kNearJump); |
| 340 __ Bind(&false_label); | 340 __ Bind(&false_label); |
| 341 __ LoadObject(EAX, compiler->bool_false()); | 341 __ LoadObject(EAX, compiler->bool_false()); |
| 342 __ Bind(&done); | 342 __ Bind(&done); |
| 343 } | 343 } |
| 344 } | 344 } |
| 345 | 345 |
| 346 | 346 |
| 347 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 347 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 348 const ICData& orig_ic_data, | 348 const ICData& orig_ic_data, |
| 349 const LocationSummary& locs, | 349 const LocationSummary& locs, |
| 350 BranchInstr* branch, | 350 BranchInstr* branch, |
| 351 Token::Kind kind, | 351 Token::Kind kind, |
| 352 intptr_t cid, | 352 intptr_t deopt_id, |
| 353 intptr_t token_pos, | 353 intptr_t token_pos, |
| 354 intptr_t try_index) { | 354 intptr_t try_index) { |
| 355 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 355 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 356 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 356 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 357 ASSERT(ic_data.NumberOfChecks() > 0); | 357 ASSERT(ic_data.NumberOfChecks() > 0); |
| 358 ASSERT(ic_data.num_args_tested() == 1); | 358 ASSERT(ic_data.num_args_tested() == 1); |
| 359 Label* deopt = compiler->AddDeoptStub(cid, | 359 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 360 token_pos, | 360 token_pos, |
| 361 try_index, | 361 try_index, |
| 362 kDeoptEquality); | 362 kDeoptEquality); |
| 363 Register left = locs.in(0).reg(); | 363 Register left = locs.in(0).reg(); |
| 364 Register right = locs.in(1).reg(); | 364 Register right = locs.in(1).reg(); |
| 365 __ testl(left, Immediate(kSmiTagMask)); | 365 __ testl(left, Immediate(kSmiTagMask)); |
| 366 Register temp = locs.temp(0).reg(); | 366 Register temp = locs.temp(0).reg(); |
| 367 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 367 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
| 368 Label done, load_class_id; | 368 Label done, load_class_id; |
| 369 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 369 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 397 Label load_true; | 397 Label load_true; |
| 398 __ j(cond, &load_true, Assembler::kNearJump); | 398 __ j(cond, &load_true, Assembler::kNearJump); |
| 399 __ LoadObject(result, compiler->bool_false()); | 399 __ LoadObject(result, compiler->bool_false()); |
| 400 __ jmp(&done); | 400 __ jmp(&done); |
| 401 __ Bind(&load_true); | 401 __ Bind(&load_true); |
| 402 __ LoadObject(result, compiler->bool_true()); | 402 __ LoadObject(result, compiler->bool_true()); |
| 403 } | 403 } |
| 404 } else { | 404 } else { |
| 405 const int kNumberOfArguments = 2; | 405 const int kNumberOfArguments = 2; |
| 406 const Array& kNoArgumentNames = Array::Handle(); | 406 const Array& kNoArgumentNames = Array::Handle(); |
| 407 compiler->GenerateStaticCall(cid, | 407 compiler->GenerateStaticCall(deopt_id, |
| 408 token_pos, | 408 token_pos, |
| 409 try_index, | 409 try_index, |
| 410 target, | 410 target, |
| 411 kNumberOfArguments, | 411 kNumberOfArguments, |
| 412 kNoArgumentNames); | 412 kNoArgumentNames); |
| 413 if (branch == NULL) { | 413 if (branch == NULL) { |
| 414 if (kind == Token::kNE) { | 414 if (kind == Token::kNE) { |
| 415 Label false_label; | 415 Label false_label; |
| 416 __ CompareObject(EAX, compiler->bool_true()); | 416 __ CompareObject(EAX, compiler->bool_true()); |
| 417 __ j(EQUAL, &false_label, Assembler::kNearJump); | 417 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 436 | 436 |
| 437 | 437 |
| 438 // First test if receiver is NULL, in which case === is applied. | 438 // First test if receiver is NULL, in which case === is applied. |
| 439 // If type feedback was provided (lists of <class-id, target>), do a | 439 // If type feedback was provided (lists of <class-id, target>), do a |
| 440 // type by type check (either === or static call to the operator. | 440 // type by type check (either === or static call to the operator. |
| 441 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 441 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 442 const LocationSummary& locs, | 442 const LocationSummary& locs, |
| 443 Token::Kind kind, | 443 Token::Kind kind, |
| 444 BranchInstr* branch, | 444 BranchInstr* branch, |
| 445 const ICData& ic_data, | 445 const ICData& ic_data, |
| 446 intptr_t cid, | 446 intptr_t deopt_id, |
| 447 intptr_t token_pos, | 447 intptr_t token_pos, |
| 448 intptr_t try_index) { | 448 intptr_t try_index) { |
| 449 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 449 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 450 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 450 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 451 Register left = locs.in(0).reg(); | 451 Register left = locs.in(0).reg(); |
| 452 Register right = locs.in(1).reg(); | 452 Register right = locs.in(1).reg(); |
| 453 const Immediate raw_null = | 453 const Immediate raw_null = |
| 454 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 454 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 455 Label done, non_null_compare; | 455 Label done, non_null_compare; |
| 456 __ cmpl(left, raw_null); | 456 __ cmpl(left, raw_null); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 467 __ LoadObject(result, compiler->bool_false()); | 467 __ LoadObject(result, compiler->bool_false()); |
| 468 __ jmp(&done); | 468 __ jmp(&done); |
| 469 __ Bind(&load_true); | 469 __ Bind(&load_true); |
| 470 __ LoadObject(result, compiler->bool_true()); | 470 __ LoadObject(result, compiler->bool_true()); |
| 471 } | 471 } |
| 472 __ jmp(&done); | 472 __ jmp(&done); |
| 473 __ Bind(&non_null_compare); // Receiver is not null. | 473 __ Bind(&non_null_compare); // Receiver is not null. |
| 474 __ pushl(left); | 474 __ pushl(left); |
| 475 __ pushl(right); | 475 __ pushl(right); |
| 476 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 476 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 477 cid, token_pos, try_index); | 477 deopt_id, token_pos, try_index); |
| 478 __ Bind(&done); | 478 __ Bind(&done); |
| 479 } | 479 } |
| 480 | 480 |
| 481 | 481 |
| 482 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 482 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 483 if (receiver_class_id() == kSmi) { | 483 if (receiver_class_id() == kSmi) { |
| 484 EmitSmiEqualityCompare(compiler, this); | 484 EmitSmiEqualityCompare(compiler, this); |
| 485 return; | 485 return; |
| 486 } | 486 } |
| 487 if (receiver_class_id() == kDouble) { | 487 if (receiver_class_id() == kDouble) { |
| 488 EmitDoubleEqualityCompare(compiler, this); | 488 EmitDoubleEqualityCompare(compiler, this); |
| 489 return; | 489 return; |
| 490 } | 490 } |
| 491 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 491 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 492 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, | 492 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), |
| 493 *ic_data(), cid(), token_pos(), try_index()); | 493 deopt_id(), token_pos(), try_index()); |
| 494 } else { | 494 } else { |
| 495 Register left = locs()->in(0).reg(); | 495 Register left = locs()->in(0).reg(); |
| 496 Register right = locs()->in(1).reg(); | 496 Register right = locs()->in(1).reg(); |
| 497 __ pushl(left); | 497 __ pushl(left); |
| 498 __ pushl(right); | 498 __ pushl(right); |
| 499 EmitEqualityAsInstanceCall(compiler, this); | 499 EmitEqualityAsInstanceCall(compiler, this); |
| 500 } | 500 } |
| 501 } | 501 } |
| 502 | 502 |
| 503 | 503 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 515 } | 515 } |
| 516 ASSERT(operands_class_id() == kObject); | 516 ASSERT(operands_class_id() == kObject); |
| 517 return MakeCallSummary(); | 517 return MakeCallSummary(); |
| 518 } | 518 } |
| 519 | 519 |
| 520 | 520 |
| 521 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 521 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 522 const LocationSummary& locs, | 522 const LocationSummary& locs, |
| 523 Token::Kind kind, | 523 Token::Kind kind, |
| 524 BranchInstr* branch, | 524 BranchInstr* branch, |
| 525 intptr_t cid, | 525 intptr_t deopt_id, |
| 526 intptr_t token_pos, | 526 intptr_t token_pos, |
| 527 intptr_t try_index) { | 527 intptr_t try_index) { |
| 528 Register left = locs.in(0).reg(); | 528 Register left = locs.in(0).reg(); |
| 529 Register right = locs.in(1).reg(); | 529 Register right = locs.in(1).reg(); |
| 530 Register temp = locs.temp(0).reg(); | 530 Register temp = locs.temp(0).reg(); |
| 531 Label* deopt = compiler->AddDeoptStub(cid, | 531 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 532 token_pos, | 532 token_pos, |
| 533 try_index, | 533 try_index, |
| 534 kDeoptSmiCompareSmi, | 534 kDeoptSmiCompareSmi, |
| 535 left, | 535 left, |
| 536 right); | 536 right); |
| 537 __ movl(temp, left); | 537 __ movl(temp, left); |
| 538 __ orl(temp, right); | 538 __ orl(temp, right); |
| 539 __ testl(temp, Immediate(kSmiTagMask)); | 539 __ testl(temp, Immediate(kSmiTagMask)); |
| 540 __ j(NOT_ZERO, deopt); | 540 __ j(NOT_ZERO, deopt); |
| 541 | 541 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 569 UNREACHABLE(); | 569 UNREACHABLE(); |
| 570 return OVERFLOW; | 570 return OVERFLOW; |
| 571 } | 571 } |
| 572 } | 572 } |
| 573 | 573 |
| 574 | 574 |
| 575 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, | 575 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, |
| 576 const LocationSummary& locs, | 576 const LocationSummary& locs, |
| 577 Token::Kind kind, | 577 Token::Kind kind, |
| 578 BranchInstr* branch, | 578 BranchInstr* branch, |
| 579 intptr_t cid, | 579 intptr_t deopt_id, |
| 580 intptr_t token_pos, | 580 intptr_t token_pos, |
| 581 intptr_t try_index) { | 581 intptr_t try_index) { |
| 582 Register left = locs.in(0).reg(); | 582 Register left = locs.in(0).reg(); |
| 583 Register right = locs.in(1).reg(); | 583 Register right = locs.in(1).reg(); |
| 584 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 584 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 585 Register temp = locs.temp(0).reg(); | 585 Register temp = locs.temp(0).reg(); |
| 586 Label* deopt = compiler->AddDeoptStub(cid, | 586 Label* deopt = compiler->AddDeoptStub(deopt_id, |
| 587 token_pos, | 587 token_pos, |
| 588 try_index, | 588 try_index, |
| 589 kDeoptDoubleComparison, | 589 kDeoptDoubleComparison, |
| 590 left, | 590 left, |
| 591 right); | 591 right); |
| 592 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 592 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 593 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 593 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 594 | 594 |
| 595 Condition true_condition = TokenKindToDoubleCondition(kind); | 595 Condition true_condition = TokenKindToDoubleCondition(kind); |
| 596 if (branch != NULL) { | 596 if (branch != NULL) { |
| 597 compiler->EmitDoubleCompareBranch( | 597 compiler->EmitDoubleCompareBranch( |
| 598 true_condition, XMM0, XMM1, branch); | 598 true_condition, XMM0, XMM1, branch); |
| 599 } else { | 599 } else { |
| 600 compiler->EmitDoubleCompareBool( | 600 compiler->EmitDoubleCompareBool( |
| 601 true_condition, XMM0, XMM1, locs.out().reg()); | 601 true_condition, XMM0, XMM1, locs.out().reg()); |
| 602 } | 602 } |
| 603 } | 603 } |
| 604 | 604 |
| 605 | 605 |
| 606 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 606 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 607 if (operands_class_id() == kSmi) { | 607 if (operands_class_id() == kSmi) { |
| 608 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, | 608 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, |
| 609 cid(), token_pos(), try_index()); | 609 deopt_id(), token_pos(), try_index()); |
| 610 return; | 610 return; |
| 611 } | 611 } |
| 612 if (operands_class_id() == kDouble) { | 612 if (operands_class_id() == kDouble) { |
| 613 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, | 613 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, |
| 614 cid(), token_pos(), try_index()); | 614 deopt_id(), token_pos(), try_index()); |
| 615 return; | 615 return; |
| 616 } | 616 } |
| 617 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 617 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 618 Label* deopt = compiler->AddDeoptStub(cid(), | 618 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 619 token_pos(), | 619 token_pos(), |
| 620 try_index(), | 620 try_index(), |
| 621 kDeoptRelationalOp); | 621 kDeoptRelationalOp); |
| 622 // Load receiver into EAX, class into EDI. | 622 // Load receiver into EAX, class into EDI. |
| 623 Label done; | 623 Label done; |
| 624 const intptr_t kNumArguments = 2; | 624 const intptr_t kNumArguments = 2; |
| 625 __ movl(EDI, Immediate(kSmi)); | 625 __ movl(EDI, Immediate(kSmi)); |
| 626 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 626 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 627 __ testl(EAX, Immediate(kSmiTagMask)); | 627 __ testl(EAX, Immediate(kSmiTagMask)); |
| 628 __ j(ZERO, &done); | 628 __ j(ZERO, &done); |
| 629 __ LoadClassId(EDI, EAX); | 629 __ LoadClassId(EDI, EAX); |
| 630 __ Bind(&done); | 630 __ Bind(&done); |
| 631 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 631 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 632 EDI, // Class id register. | 632 EDI, // Class id register. |
| 633 kNumArguments, | 633 kNumArguments, |
| 634 Array::Handle(), // No named arguments. | 634 Array::Handle(), // No named arguments. |
| 635 deopt, // Deoptimize target. | 635 deopt, // Deoptimize target. |
| 636 NULL, // Fallthrough when done. | 636 NULL, // Fallthrough when done. |
| 637 cid(), | 637 deopt_id(), |
| 638 token_pos(), | 638 token_pos(), |
| 639 try_index()); | 639 try_index()); |
| 640 return; | 640 return; |
| 641 } | 641 } |
| 642 const String& function_name = | 642 const String& function_name = |
| 643 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 643 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 644 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 644 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 645 cid(), | 645 deopt_id(), |
| 646 token_pos(), | 646 token_pos(), |
| 647 try_index()); | 647 try_index()); |
| 648 const intptr_t kNumArguments = 2; | 648 const intptr_t kNumArguments = 2; |
| 649 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 649 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 650 compiler->GenerateInstanceCall(cid(), | 650 compiler->GenerateInstanceCall(deopt_id(), |
| 651 token_pos(), | 651 token_pos(), |
| 652 try_index(), | 652 try_index(), |
| 653 function_name, | 653 function_name, |
| 654 kNumArguments, | 654 kNumArguments, |
| 655 Array::ZoneHandle(), // No optional arguments. | 655 Array::ZoneHandle(), // No optional arguments. |
| 656 kNumArgsChecked); | 656 kNumArgsChecked); |
| 657 ASSERT(locs()->out().reg() == EAX); | 657 ASSERT(locs()->out().reg() == EAX); |
| 658 } | 658 } |
| 659 | 659 |
| 660 | 660 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 return locs; | 715 return locs; |
| 716 } else { | 716 } else { |
| 717 ASSERT(receiver_type() == kIllegalObjectKind); | 717 ASSERT(receiver_type() == kIllegalObjectKind); |
| 718 return MakeCallSummary(); | 718 return MakeCallSummary(); |
| 719 } | 719 } |
| 720 } | 720 } |
| 721 | 721 |
| 722 | 722 |
| 723 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 723 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 724 LoadIndexedComp* comp) { | 724 LoadIndexedComp* comp) { |
| 725 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 725 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 726 comp->token_pos(), | 726 comp->token_pos(), |
| 727 comp->try_index(), | 727 comp->try_index(), |
| 728 kDeoptLoadIndexedPolymorphic); | 728 kDeoptLoadIndexedPolymorphic); |
| 729 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 729 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 730 ASSERT(comp->HasICData()); | 730 ASSERT(comp->HasICData()); |
| 731 const ICData& ic_data = *comp->ic_data(); | 731 const ICData& ic_data = *comp->ic_data(); |
| 732 ASSERT(ic_data.num_args_tested() == 1); | 732 ASSERT(ic_data.num_args_tested() == 1); |
| 733 // No indexed access on Smi. | 733 // No indexed access on Smi. |
| 734 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 734 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 735 // Load receiver into EAX. | 735 // Load receiver into EAX. |
| 736 const intptr_t kNumArguments = 2; | 736 const intptr_t kNumArguments = 2; |
| 737 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 737 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 738 __ testl(EAX, Immediate(kSmiTagMask)); | 738 __ testl(EAX, Immediate(kSmiTagMask)); |
| 739 __ j(ZERO, deopt); | 739 __ j(ZERO, deopt); |
| 740 __ LoadClassId(EDI, EAX); | 740 __ LoadClassId(EDI, EAX); |
| 741 compiler->EmitTestAndCall(ic_data, | 741 compiler->EmitTestAndCall(ic_data, |
| 742 EDI, // Class id register. | 742 EDI, // Class id register. |
| 743 kNumArguments, | 743 kNumArguments, |
| 744 Array::Handle(), // No named arguments. | 744 Array::Handle(), // No named arguments. |
| 745 deopt, // Deoptimize target. | 745 deopt, // Deoptimize target. |
| 746 NULL, // Fallthrough when done. | 746 NULL, // Fallthrough when done. |
| 747 comp->cid(), | 747 comp->deopt_id(), |
| 748 comp->token_pos(), | 748 comp->token_pos(), |
| 749 comp->try_index()); | 749 comp->try_index()); |
| 750 } | 750 } |
| 751 | 751 |
| 752 | 752 |
| 753 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 753 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 754 if (receiver_type() == kIllegalObjectKind) { | 754 if (receiver_type() == kIllegalObjectKind) { |
| 755 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 755 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 756 EmitLoadIndexedPolymorphic(compiler, this); | 756 EmitLoadIndexedPolymorphic(compiler, this); |
| 757 } else { | 757 } else { |
| 758 compiler->EmitLoadIndexedGeneric(this); | 758 compiler->EmitLoadIndexedGeneric(this); |
| 759 } | 759 } |
| 760 ASSERT(locs()->out().reg() == EAX); | 760 ASSERT(locs()->out().reg() == EAX); |
| 761 return; | 761 return; |
| 762 } | 762 } |
| 763 | 763 |
| 764 Register receiver = locs()->in(0).reg(); | 764 Register receiver = locs()->in(0).reg(); |
| 765 Register index = locs()->in(1).reg(); | 765 Register index = locs()->in(1).reg(); |
| 766 Register result = locs()->out().reg(); | 766 Register result = locs()->out().reg(); |
| 767 Register temp = locs()->temp(0).reg(); | 767 Register temp = locs()->temp(0).reg(); |
| 768 | 768 |
| 769 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 769 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
| 770 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 770 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 771 | 771 |
| 772 Label* deopt = compiler->AddDeoptStub(cid(), | 772 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 773 token_pos(), | 773 token_pos(), |
| 774 try_index(), | 774 try_index(), |
| 775 deopt_reason, | 775 deopt_reason, |
| 776 receiver, | 776 receiver, |
| 777 index); | 777 index); |
| 778 | 778 |
| 779 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 779 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 780 __ j(ZERO, deopt); | 780 __ j(ZERO, deopt); |
| 781 __ CompareClassId(receiver, receiver_type(), temp); | 781 __ CompareClassId(receiver, receiver_type(), temp); |
| 782 __ j(NOT_EQUAL, deopt); | 782 __ j(NOT_EQUAL, deopt); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 833 } | 833 } |
| 834 } | 834 } |
| 835 | 835 |
| 836 | 836 |
| 837 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 837 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
| 838 StoreIndexedComp* comp) { | 838 StoreIndexedComp* comp) { |
| 839 const String& function_name = | 839 const String& function_name = |
| 840 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); | 840 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); |
| 841 | 841 |
| 842 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 842 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 843 comp->cid(), | 843 comp->deopt_id(), |
| 844 comp->token_pos(), | 844 comp->token_pos(), |
| 845 comp->try_index()); | 845 comp->try_index()); |
| 846 | 846 |
| 847 const intptr_t kNumArguments = 3; | 847 const intptr_t kNumArguments = 3; |
| 848 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 848 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 849 compiler->GenerateInstanceCall(comp->cid(), | 849 compiler->GenerateInstanceCall(comp->deopt_id(), |
| 850 comp->token_pos(), | 850 comp->token_pos(), |
| 851 comp->try_index(), | 851 comp->try_index(), |
| 852 function_name, | 852 function_name, |
| 853 kNumArguments, | 853 kNumArguments, |
| 854 Array::ZoneHandle(), // No named arguments. | 854 Array::ZoneHandle(), // No named arguments. |
| 855 kNumArgsChecked); | 855 kNumArgsChecked); |
| 856 } | 856 } |
| 857 | 857 |
| 858 | 858 |
| 859 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 859 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 860 StoreIndexedComp* comp) { | 860 StoreIndexedComp* comp) { |
| 861 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 861 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 862 comp->token_pos(), | 862 comp->token_pos(), |
| 863 comp->try_index(), | 863 comp->try_index(), |
| 864 kDeoptStoreIndexedPolymorphic); | 864 kDeoptStoreIndexedPolymorphic); |
| 865 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 865 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 866 ASSERT(comp->HasICData()); | 866 ASSERT(comp->HasICData()); |
| 867 const ICData& ic_data = *comp->ic_data(); | 867 const ICData& ic_data = *comp->ic_data(); |
| 868 ASSERT(ic_data.num_args_tested() == 1); | 868 ASSERT(ic_data.num_args_tested() == 1); |
| 869 // No indexed access on Smi. | 869 // No indexed access on Smi. |
| 870 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 870 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 871 // Load receiver into EAX. | 871 // Load receiver into EAX. |
| 872 const intptr_t kNumArguments = 3; | 872 const intptr_t kNumArguments = 3; |
| 873 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 873 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 874 __ testl(EAX, Immediate(kSmiTagMask)); | 874 __ testl(EAX, Immediate(kSmiTagMask)); |
| 875 __ j(ZERO, deopt); | 875 __ j(ZERO, deopt); |
| 876 __ LoadClassId(EDI, EAX); | 876 __ LoadClassId(EDI, EAX); |
| 877 compiler->EmitTestAndCall(ic_data, | 877 compiler->EmitTestAndCall(ic_data, |
| 878 EDI, // Class id register. | 878 EDI, // Class id register. |
| 879 kNumArguments, | 879 kNumArguments, |
| 880 Array::Handle(), // No named arguments. | 880 Array::Handle(), // No named arguments. |
| 881 deopt, // Deoptimize target. | 881 deopt, // Deoptimize target. |
| 882 NULL, // Fallthrough when done. | 882 NULL, // Fallthrough when done. |
| 883 comp->cid(), | 883 comp->deopt_id(), |
| 884 comp->token_pos(), | 884 comp->token_pos(), |
| 885 comp->try_index()); | 885 comp->try_index()); |
| 886 } | 886 } |
| 887 | 887 |
| 888 | 888 |
| 889 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 889 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 890 if (receiver_type() == kIllegalObjectKind) { | 890 if (receiver_type() == kIllegalObjectKind) { |
| 891 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 891 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 892 EmitStoreIndexedPolymorphic(compiler, this); | 892 EmitStoreIndexedPolymorphic(compiler, this); |
| 893 } else { | 893 } else { |
| 894 EmitStoreIndexedGeneric(compiler, this); | 894 EmitStoreIndexedGeneric(compiler, this); |
| 895 } | 895 } |
| 896 return; | 896 return; |
| 897 } | 897 } |
| 898 | 898 |
| 899 Register receiver = locs()->in(0).reg(); | 899 Register receiver = locs()->in(0).reg(); |
| 900 Register index = locs()->in(1).reg(); | 900 Register index = locs()->in(1).reg(); |
| 901 Register value = locs()->in(2).reg(); | 901 Register value = locs()->in(2).reg(); |
| 902 Register temp = locs()->temp(0).reg(); | 902 Register temp = locs()->temp(0).reg(); |
| 903 | 903 |
| 904 Label* deopt = compiler->AddDeoptStub(cid(), | 904 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 905 token_pos(), | 905 token_pos(), |
| 906 try_index(), | 906 try_index(), |
| 907 kDeoptStoreIndexed, | 907 kDeoptStoreIndexed, |
| 908 receiver, | 908 receiver, |
| 909 index, | 909 index, |
| 910 value); | 910 value); |
| 911 | 911 |
| 912 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 912 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 913 __ j(ZERO, deopt); | 913 __ j(ZERO, deopt); |
| 914 __ CompareClassId(receiver, receiver_type(), temp); | 914 __ CompareClassId(receiver, receiver_type(), temp); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 LocationSummary::kNoCall); | 959 LocationSummary::kNoCall); |
| 960 } | 960 } |
| 961 | 961 |
| 962 | 962 |
| 963 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 963 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 964 Register instance_reg = locs()->in(0).reg(); | 964 Register instance_reg = locs()->in(0).reg(); |
| 965 Register result_reg = locs()->out().reg(); | 965 Register result_reg = locs()->out().reg(); |
| 966 | 966 |
| 967 if (HasICData()) { | 967 if (HasICData()) { |
| 968 ASSERT(original() != NULL); | 968 ASSERT(original() != NULL); |
| 969 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 969 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 970 original()->token_pos(), | 970 original()->token_pos(), |
| 971 original()->try_index(), | 971 original()->try_index(), |
| 972 kDeoptInstanceGetterSameTarget, | 972 kDeoptInstanceGetterSameTarget, |
| 973 instance_reg); | 973 instance_reg); |
| 974 // Smis do not have instance fields (Smi class is always first). | 974 // Smis do not have instance fields (Smi class is always first). |
| 975 // Use 'result' as temporary register. | 975 // Use 'result' as temporary register. |
| 976 ASSERT(result_reg != instance_reg); | 976 ASSERT(result_reg != instance_reg); |
| 977 ASSERT(ic_data() != NULL); | 977 ASSERT(ic_data() != NULL); |
| 978 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 978 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 979 } | 979 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1006 summary->set_out(Location::RegisterLocation(EAX)); | 1006 summary->set_out(Location::RegisterLocation(EAX)); |
| 1007 return summary; | 1007 return summary; |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 | 1010 |
| 1011 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1011 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1012 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1012 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 1013 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 1013 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 1014 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 1014 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 1015 | 1015 |
| 1016 compiler->GenerateInstanceOf(cid(), | 1016 compiler->GenerateInstanceOf(deopt_id(), |
| 1017 token_pos(), | 1017 token_pos(), |
| 1018 try_index(), | 1018 try_index(), |
| 1019 type(), | 1019 type(), |
| 1020 negate_result()); | 1020 negate_result()); |
| 1021 ASSERT(locs()->out().reg() == EAX); | 1021 ASSERT(locs()->out().reg() == EAX); |
| 1022 } | 1022 } |
| 1023 | 1023 |
| 1024 | 1024 |
| 1025 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1025 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 1026 return MakeCallSummary(); | 1026 return MakeCallSummary(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1065 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 1066 Register type_arguments = locs()->in(0).reg(); | 1066 Register type_arguments = locs()->in(0).reg(); |
| 1067 Register instantiator_type_arguments = locs()->in(1).reg(); | 1067 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 1068 Register result = locs()->out().reg(); | 1068 Register result = locs()->out().reg(); |
| 1069 | 1069 |
| 1070 // Push the result place holder initialized to NULL. | 1070 // Push the result place holder initialized to NULL. |
| 1071 __ PushObject(Object::ZoneHandle()); | 1071 __ PushObject(Object::ZoneHandle()); |
| 1072 __ PushObject(cls); | 1072 __ PushObject(cls); |
| 1073 __ pushl(type_arguments); | 1073 __ pushl(type_arguments); |
| 1074 __ pushl(instantiator_type_arguments); | 1074 __ pushl(instantiator_type_arguments); |
| 1075 compiler->GenerateCallRuntime(cid(), | 1075 compiler->GenerateCallRuntime(deopt_id(), |
| 1076 token_pos(), | 1076 token_pos(), |
| 1077 try_index(), | 1077 try_index(), |
| 1078 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1078 kAllocateObjectWithBoundsCheckRuntimeEntry); |
| 1079 // Pop instantiator type arguments, type arguments, and class. | 1079 // Pop instantiator type arguments, type arguments, and class. |
| 1080 // source location. | 1080 // source location. |
| 1081 __ Drop(3); | 1081 __ Drop(3); |
| 1082 __ popl(result); // Pop new instance. | 1082 __ popl(result); // Pop new instance. |
| 1083 } | 1083 } |
| 1084 | 1084 |
| 1085 | 1085 |
| 1086 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1086 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| 1087 return LocationSummary::Make(1, | 1087 return LocationSummary::Make(1, |
| 1088 Location::RequiresRegister(), | 1088 Location::RequiresRegister(), |
| 1089 LocationSummary::kNoCall); | 1089 LocationSummary::kNoCall); |
| 1090 } | 1090 } |
| 1091 | 1091 |
| 1092 | 1092 |
| 1093 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1093 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1094 Register instance_reg = locs()->in(0).reg(); | 1094 Register instance_reg = locs()->in(0).reg(); |
| 1095 Register result_reg = locs()->out().reg(); | 1095 Register result_reg = locs()->out().reg(); |
| 1096 if (HasICData()) { | 1096 if (HasICData()) { |
| 1097 ASSERT(original() != NULL); | 1097 ASSERT(original() != NULL); |
| 1098 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1098 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(), |
| 1099 original()->token_pos(), | 1099 original()->token_pos(), |
| 1100 original()->try_index(), | 1100 original()->try_index(), |
| 1101 kDeoptInstanceGetterSameTarget, | 1101 kDeoptInstanceGetterSameTarget, |
| 1102 instance_reg); | 1102 instance_reg); |
| 1103 // Smis do not have instance fields (Smi class is always first). | 1103 // Smis do not have instance fields (Smi class is always first). |
| 1104 // Use 'result' as temporary register. | 1104 // Use 'result' as temporary register. |
| 1105 ASSERT(result_reg != instance_reg); | 1105 ASSERT(result_reg != instance_reg); |
| 1106 ASSERT(ic_data() != NULL); | 1106 ASSERT(ic_data() != NULL); |
| 1107 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1107 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1108 } | 1108 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1154 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1154 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1155 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1155 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1156 Immediate(Smi::RawValue(len))); | 1156 Immediate(Smi::RawValue(len))); |
| 1157 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1157 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1158 __ Bind(&type_arguments_uninstantiated); | 1158 __ Bind(&type_arguments_uninstantiated); |
| 1159 } | 1159 } |
| 1160 // A runtime call to instantiate the type arguments is required. | 1160 // A runtime call to instantiate the type arguments is required. |
| 1161 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1161 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1162 __ PushObject(type_arguments()); | 1162 __ PushObject(type_arguments()); |
| 1163 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1163 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 1164 compiler->GenerateCallRuntime(cid(), | 1164 compiler->GenerateCallRuntime(deopt_id(), |
| 1165 token_pos(), | 1165 token_pos(), |
| 1166 try_index(), | 1166 try_index(), |
| 1167 kInstantiateTypeArgumentsRuntimeEntry); | 1167 kInstantiateTypeArgumentsRuntimeEntry); |
| 1168 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1168 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1169 __ popl(result_reg); // Pop instantiated type arguments. | 1169 __ popl(result_reg); // Pop instantiated type arguments. |
| 1170 __ Bind(&type_arguments_instantiated); | 1170 __ Bind(&type_arguments_instantiated); |
| 1171 ASSERT(instantiator_reg == result_reg); | 1171 ASSERT(instantiator_reg == result_reg); |
| 1172 // 'result_reg': Instantiated type arguments. | 1172 // 'result_reg': Instantiated type arguments. |
| 1173 } | 1173 } |
| 1174 | 1174 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1334 return locs; | 1334 return locs; |
| 1335 } | 1335 } |
| 1336 | 1336 |
| 1337 | 1337 |
| 1338 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1338 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1339 Register context_value = locs()->in(0).reg(); | 1339 Register context_value = locs()->in(0).reg(); |
| 1340 Register result = locs()->out().reg(); | 1340 Register result = locs()->out().reg(); |
| 1341 | 1341 |
| 1342 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1342 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1343 __ pushl(context_value); | 1343 __ pushl(context_value); |
| 1344 compiler->GenerateCallRuntime(cid(), | 1344 compiler->GenerateCallRuntime(deopt_id(), |
| 1345 token_pos(), | 1345 token_pos(), |
| 1346 try_index(), | 1346 try_index(), |
| 1347 kCloneContextRuntimeEntry); | 1347 kCloneContextRuntimeEntry); |
| 1348 __ popl(result); // Remove argument. | 1348 __ popl(result); // Remove argument. |
| 1349 __ popl(result); // Get result (cloned context). | 1349 __ popl(result); // Get result (cloned context). |
| 1350 } | 1350 } |
| 1351 | 1351 |
| 1352 | 1352 |
| 1353 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1353 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1354 return LocationSummary::Make(0, | 1354 return LocationSummary::Make(0, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1385 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1386 return summary; | 1386 return summary; |
| 1387 } | 1387 } |
| 1388 | 1388 |
| 1389 | 1389 |
| 1390 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1390 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1391 __ cmpl(ESP, | 1391 __ cmpl(ESP, |
| 1392 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1392 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 1393 Label no_stack_overflow; | 1393 Label no_stack_overflow; |
| 1394 __ j(ABOVE, &no_stack_overflow); | 1394 __ j(ABOVE, &no_stack_overflow); |
| 1395 compiler->GenerateCallRuntime(cid(), | 1395 compiler->GenerateCallRuntime(deopt_id(), |
| 1396 token_pos(), | 1396 token_pos(), |
| 1397 try_index(), | 1397 try_index(), |
| 1398 kStackOverflowRuntimeEntry); | 1398 kStackOverflowRuntimeEntry); |
| 1399 __ Bind(&no_stack_overflow); | 1399 __ Bind(&no_stack_overflow); |
| 1400 } | 1400 } |
| 1401 | 1401 |
| 1402 | 1402 |
| 1403 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1403 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1404 const intptr_t kNumInputs = 2; | 1404 const intptr_t kNumInputs = 2; |
| 1405 | 1405 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 } | 1464 } |
| 1465 } | 1465 } |
| 1466 | 1466 |
| 1467 | 1467 |
| 1468 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1468 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1469 Register left = comp->locs()->in(0).reg(); | 1469 Register left = comp->locs()->in(0).reg(); |
| 1470 Register right = comp->locs()->in(1).reg(); | 1470 Register right = comp->locs()->in(1).reg(); |
| 1471 Register result = comp->locs()->out().reg(); | 1471 Register result = comp->locs()->out().reg(); |
| 1472 Register temp = comp->locs()->temp(0).reg(); | 1472 Register temp = comp->locs()->temp(0).reg(); |
| 1473 ASSERT(left == result); | 1473 ASSERT(left == result); |
| 1474 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1474 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1475 comp->instance_call()->token_pos(), | 1475 comp->instance_call()->token_pos(), |
| 1476 comp->instance_call()->try_index(), | 1476 comp->instance_call()->try_index(), |
| 1477 kDeoptSmiBinaryOp, | 1477 kDeoptSmiBinaryOp, |
| 1478 temp, | 1478 temp, |
| 1479 right); | 1479 right); |
| 1480 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1480 // TODO(vegorov): for many binary operations this pattern can be rearranged |
| 1481 // to save one move. | 1481 // to save one move. |
| 1482 __ movl(temp, left); | 1482 __ movl(temp, left); |
| 1483 __ orl(left, right); | 1483 __ orl(left, right); |
| 1484 __ testl(left, Immediate(kSmiTagMask)); | 1484 __ testl(left, Immediate(kSmiTagMask)); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1575 __ shll(left, right_temp); | 1575 __ shll(left, right_temp); |
| 1576 __ jmp(&done); | 1576 __ jmp(&done); |
| 1577 { | 1577 { |
| 1578 __ Bind(&call_method); | 1578 __ Bind(&call_method); |
| 1579 Function& target = Function::ZoneHandle( | 1579 Function& target = Function::ZoneHandle( |
| 1580 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1580 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1581 ASSERT(!target.IsNull()); | 1581 ASSERT(!target.IsNull()); |
| 1582 const intptr_t kArgumentCount = 2; | 1582 const intptr_t kArgumentCount = 2; |
| 1583 __ pushl(temp); | 1583 __ pushl(temp); |
| 1584 __ pushl(right); | 1584 __ pushl(right); |
| 1585 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1585 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
| 1586 comp->instance_call()->token_pos(), | 1586 comp->instance_call()->token_pos(), |
| 1587 comp->instance_call()->try_index(), | 1587 comp->instance_call()->try_index(), |
| 1588 target, | 1588 target, |
| 1589 kArgumentCount, | 1589 kArgumentCount, |
| 1590 Array::Handle()); // No argument names. | 1590 Array::Handle()); // No argument names. |
| 1591 ASSERT(result == EAX); | 1591 ASSERT(result == EAX); |
| 1592 } | 1592 } |
| 1593 __ Bind(&done); | 1593 __ Bind(&done); |
| 1594 break; | 1594 break; |
| 1595 } | 1595 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1622 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1622 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1623 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1623 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1624 // both receiver and argument are Mint or if one of them is Mint and the other | 1624 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1625 // is a negative Smi. | 1625 // is a negative Smi. |
| 1626 Register left = comp->locs()->in(0).reg(); | 1626 Register left = comp->locs()->in(0).reg(); |
| 1627 Register right = comp->locs()->in(1).reg(); | 1627 Register right = comp->locs()->in(1).reg(); |
| 1628 Register result = comp->locs()->out().reg(); | 1628 Register result = comp->locs()->out().reg(); |
| 1629 Register temp = comp->locs()->temp(0).reg(); | 1629 Register temp = comp->locs()->temp(0).reg(); |
| 1630 ASSERT(left == result); | 1630 ASSERT(left == result); |
| 1631 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1631 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1632 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1632 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(), |
| 1633 comp->instance_call()->token_pos(), | 1633 comp->instance_call()->token_pos(), |
| 1634 comp->instance_call()->try_index(), | 1634 comp->instance_call()->try_index(), |
| 1635 kDeoptMintBinaryOp, | 1635 kDeoptMintBinaryOp, |
| 1636 left, | 1636 left, |
| 1637 right); | 1637 right); |
| 1638 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1638 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1639 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1639 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1640 __ j(NOT_ZERO, &non_smi); | 1640 __ j(NOT_ZERO, &non_smi); |
| 1641 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1641 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1642 __ j(ZERO, &smi_smi); | 1642 __ j(ZERO, &smi_smi); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1670 | 1670 |
| 1671 __ Bind(&smi_static_call); | 1671 __ Bind(&smi_static_call); |
| 1672 { | 1672 { |
| 1673 Function& target = Function::ZoneHandle( | 1673 Function& target = Function::ZoneHandle( |
| 1674 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1674 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1675 if (target.IsNull()) { | 1675 if (target.IsNull()) { |
| 1676 __ jmp(deopt); | 1676 __ jmp(deopt); |
| 1677 } else { | 1677 } else { |
| 1678 __ pushl(left); | 1678 __ pushl(left); |
| 1679 __ pushl(right); | 1679 __ pushl(right); |
| 1680 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1680 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
| 1681 comp->instance_call()->token_pos(), | 1681 comp->instance_call()->token_pos(), |
| 1682 comp->instance_call()->try_index(), | 1682 comp->instance_call()->try_index(), |
| 1683 target, | 1683 target, |
| 1684 comp->instance_call()->ArgumentCount(), | 1684 comp->instance_call()->ArgumentCount(), |
| 1685 comp->instance_call()->argument_names()); | 1685 comp->instance_call()->argument_names()); |
| 1686 ASSERT(result == EAX); | 1686 ASSERT(result == EAX); |
| 1687 __ jmp(&done); | 1687 __ jmp(&done); |
| 1688 } | 1688 } |
| 1689 } | 1689 } |
| 1690 | 1690 |
| 1691 __ Bind(&mint_static_call); | 1691 __ Bind(&mint_static_call); |
| 1692 { | 1692 { |
| 1693 Function& target = Function::ZoneHandle( | 1693 Function& target = Function::ZoneHandle( |
| 1694 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1694 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
| 1695 if (target.IsNull()) { | 1695 if (target.IsNull()) { |
| 1696 __ jmp(deopt); | 1696 __ jmp(deopt); |
| 1697 } else { | 1697 } else { |
| 1698 __ pushl(left); | 1698 __ pushl(left); |
| 1699 __ pushl(right); | 1699 __ pushl(right); |
| 1700 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1700 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), |
| 1701 comp->instance_call()->token_pos(), | 1701 comp->instance_call()->token_pos(), |
| 1702 comp->instance_call()->try_index(), | 1702 comp->instance_call()->try_index(), |
| 1703 target, | 1703 target, |
| 1704 comp->instance_call()->ArgumentCount(), | 1704 comp->instance_call()->ArgumentCount(), |
| 1705 comp->instance_call()->argument_names()); | 1705 comp->instance_call()->argument_names()); |
| 1706 ASSERT(result == EAX); | 1706 ASSERT(result == EAX); |
| 1707 } | 1707 } |
| 1708 } | 1708 } |
| 1709 __ Bind(&done); | 1709 __ Bind(&done); |
| 1710 } | 1710 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1743 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1743 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1744 compiler->GenerateCall(instance_call()->token_pos(), | 1744 compiler->GenerateCall(instance_call()->token_pos(), |
| 1745 instance_call()->try_index(), | 1745 instance_call()->try_index(), |
| 1746 &label, | 1746 &label, |
| 1747 PcDescriptors::kOther); | 1747 PcDescriptors::kOther); |
| 1748 // Newly allocated object is now in the result register (RAX). | 1748 // Newly allocated object is now in the result register (RAX). |
| 1749 ASSERT(result == EAX); | 1749 ASSERT(result == EAX); |
| 1750 __ popl(right); | 1750 __ popl(right); |
| 1751 __ popl(left); | 1751 __ popl(left); |
| 1752 | 1752 |
| 1753 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1753 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1754 instance_call()->token_pos(), | 1754 instance_call()->token_pos(), |
| 1755 instance_call()->try_index(), | 1755 instance_call()->try_index(), |
| 1756 kDeoptDoubleBinaryOp, | 1756 kDeoptDoubleBinaryOp, |
| 1757 left, | 1757 left, |
| 1758 right); | 1758 right); |
| 1759 | 1759 |
| 1760 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1760 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1761 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1761 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 1762 | 1762 |
| 1763 switch (op_kind()) { | 1763 switch (op_kind()) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1789 ASSERT(ic_data.num_args_tested() == 1); | 1789 ASSERT(ic_data.num_args_tested() == 1); |
| 1790 // TODO(srdjan): Implement for more checks. | 1790 // TODO(srdjan): Implement for more checks. |
| 1791 ASSERT(ic_data.NumberOfChecks() == 1); | 1791 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1792 intptr_t test_class_id; | 1792 intptr_t test_class_id; |
| 1793 Function& target = Function::Handle(); | 1793 Function& target = Function::Handle(); |
| 1794 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1794 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1795 | 1795 |
| 1796 Register value = locs()->in(0).reg(); | 1796 Register value = locs()->in(0).reg(); |
| 1797 Register result = locs()->out().reg(); | 1797 Register result = locs()->out().reg(); |
| 1798 ASSERT(value == result); | 1798 ASSERT(value == result); |
| 1799 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1799 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1800 instance_call()->token_pos(), | 1800 instance_call()->token_pos(), |
| 1801 instance_call()->try_index(), | 1801 instance_call()->try_index(), |
| 1802 kDeoptUnaryOp, | 1802 kDeoptUnaryOp, |
| 1803 value); | 1803 value); |
| 1804 if (test_class_id == kSmi) { | 1804 if (test_class_id == kSmi) { |
| 1805 __ testl(value, Immediate(kSmiTagMask)); | 1805 __ testl(value, Immediate(kSmiTagMask)); |
| 1806 __ j(NOT_ZERO, deopt); | 1806 __ j(NOT_ZERO, deopt); |
| 1807 switch (op_kind()) { | 1807 switch (op_kind()) { |
| 1808 case Token::kNEGATE: | 1808 case Token::kNEGATE: |
| 1809 __ negl(value); | 1809 __ negl(value); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1841 | 1841 |
| 1842 // TODO(srdjan): Implement for more checks. | 1842 // TODO(srdjan): Implement for more checks. |
| 1843 ASSERT(ic_data.NumberOfChecks() == 1); | 1843 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1844 intptr_t test_class_id; | 1844 intptr_t test_class_id; |
| 1845 Function& target = Function::Handle(); | 1845 Function& target = Function::Handle(); |
| 1846 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1846 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1847 | 1847 |
| 1848 Register value = locs()->in(0).reg(); | 1848 Register value = locs()->in(0).reg(); |
| 1849 Register result = locs()->out().reg(); | 1849 Register result = locs()->out().reg(); |
| 1850 ASSERT(value == result); | 1850 ASSERT(value == result); |
| 1851 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1851 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1852 instance_call()->token_pos(), | 1852 instance_call()->token_pos(), |
| 1853 instance_call()->try_index(), | 1853 instance_call()->try_index(), |
| 1854 kDeoptUnaryOp, | 1854 kDeoptUnaryOp, |
| 1855 value); | 1855 value); |
| 1856 if (test_class_id == kDouble) { | 1856 if (test_class_id == kDouble) { |
| 1857 Register temp = locs()->temp(0).reg(); | 1857 Register temp = locs()->temp(0).reg(); |
| 1858 __ testl(value, Immediate(kSmiTagMask)); | 1858 __ testl(value, Immediate(kSmiTagMask)); |
| 1859 __ j(ZERO, deopt); // Smi. | 1859 __ j(ZERO, deopt); // Smi. |
| 1860 __ CompareClassId(value, kDouble, temp); | 1860 __ CompareClassId(value, kDouble, temp); |
| 1861 __ j(NOT_EQUAL, deopt); | 1861 __ j(NOT_EQUAL, deopt); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1899 } | 1899 } |
| 1900 } | 1900 } |
| 1901 | 1901 |
| 1902 | 1902 |
| 1903 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1903 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1904 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | 1904 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; |
| 1905 Register result = locs()->out().reg(); | 1905 Register result = locs()->out().reg(); |
| 1906 | 1906 |
| 1907 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1907 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
| 1908 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1908 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1909 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1909 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1910 instance_call()->token_pos(), | 1910 instance_call()->token_pos(), |
| 1911 instance_call()->try_index(), | 1911 instance_call()->try_index(), |
| 1912 deopt_reason, | 1912 deopt_reason, |
| 1913 value); | 1913 value); |
| 1914 | 1914 |
| 1915 if (from() == kDouble) { | 1915 if (from() == kDouble) { |
| 1916 Register temp = locs()->temp(0).reg(); | 1916 Register temp = locs()->temp(0).reg(); |
| 1917 __ testl(value, Immediate(kSmiTagMask)); | 1917 __ testl(value, Immediate(kSmiTagMask)); |
| 1918 __ j(ZERO, deopt); // Deoptimize if Smi. | 1918 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1919 __ CompareClassId(value, kDouble, temp); | 1919 __ CompareClassId(value, kDouble, temp); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1944 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1944 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1945 } | 1945 } |
| 1946 | 1946 |
| 1947 | 1947 |
| 1948 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1948 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 1949 return MakeCallSummary(); | 1949 return MakeCallSummary(); |
| 1950 } | 1950 } |
| 1951 | 1951 |
| 1952 | 1952 |
| 1953 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1953 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1954 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1954 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1955 instance_call()->token_pos(), | 1955 instance_call()->token_pos(), |
| 1956 instance_call()->try_index(), | 1956 instance_call()->try_index(), |
| 1957 kDeoptPolymorphicInstanceCallTestFail); | 1957 kDeoptPolymorphicInstanceCallTestFail); |
| 1958 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1958 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1959 __ jmp(deopt); | 1959 __ jmp(deopt); |
| 1960 return; | 1960 return; |
| 1961 } | 1961 } |
| 1962 ASSERT(HasICData()); | 1962 ASSERT(HasICData()); |
| 1963 ASSERT(ic_data()->num_args_tested() == 1); | 1963 ASSERT(ic_data()->num_args_tested() == 1); |
| 1964 Label handle_smi; | 1964 Label handle_smi; |
| 1965 Label* is_smi_label = | 1965 Label* is_smi_label = |
| 1966 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1966 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
| 1967 | 1967 |
| 1968 // Load receiver into EAX. | 1968 // Load receiver into EAX. |
| 1969 __ movl(EAX, | 1969 __ movl(EAX, |
| 1970 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1970 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 1971 __ testl(EAX, Immediate(kSmiTagMask)); | 1971 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1972 __ j(ZERO, is_smi_label); | 1972 __ j(ZERO, is_smi_label); |
| 1973 Label done; | 1973 Label done; |
| 1974 __ LoadClassId(EDI, EAX); | 1974 __ LoadClassId(EDI, EAX); |
| 1975 compiler->EmitTestAndCall(*ic_data(), | 1975 compiler->EmitTestAndCall(*ic_data(), |
| 1976 EDI, // Class id register. | 1976 EDI, // Class id register. |
| 1977 instance_call()->ArgumentCount(), | 1977 instance_call()->ArgumentCount(), |
| 1978 instance_call()->argument_names(), | 1978 instance_call()->argument_names(), |
| 1979 deopt, | 1979 deopt, |
| 1980 (is_smi_label == &handle_smi) ? &done : NULL, | 1980 (is_smi_label == &handle_smi) ? &done : NULL, |
| 1981 instance_call()->cid(), | 1981 instance_call()->deopt_id(), |
| 1982 instance_call()->token_pos(), | 1982 instance_call()->token_pos(), |
| 1983 instance_call()->try_index()); | 1983 instance_call()->try_index()); |
| 1984 if (is_smi_label == &handle_smi) { | 1984 if (is_smi_label == &handle_smi) { |
| 1985 __ Bind(&handle_smi); | 1985 __ Bind(&handle_smi); |
| 1986 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1986 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
| 1987 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1987 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1988 compiler->GenerateStaticCall(instance_call()->cid(), | 1988 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 1989 instance_call()->token_pos(), | 1989 instance_call()->token_pos(), |
| 1990 instance_call()->try_index(), | 1990 instance_call()->try_index(), |
| 1991 target, | 1991 target, |
| 1992 instance_call()->ArgumentCount(), | 1992 instance_call()->ArgumentCount(), |
| 1993 instance_call()->argument_names()); | 1993 instance_call()->argument_names()); |
| 1994 } | 1994 } |
| 1995 __ Bind(&done); | 1995 __ Bind(&done); |
| 1996 } | 1996 } |
| 1997 | 1997 |
| 1998 | 1998 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2052 Register right = locs()->in(1).reg(); | 2052 Register right = locs()->in(1).reg(); |
| 2053 __ cmpl(left, right); | 2053 __ cmpl(left, right); |
| 2054 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 2054 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 2055 EmitBranchOnCondition(compiler, cond); | 2055 EmitBranchOnCondition(compiler, cond); |
| 2056 return; | 2056 return; |
| 2057 } | 2057 } |
| 2058 // Relational or equality. | 2058 // Relational or equality. |
| 2059 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 2059 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 2060 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { | 2060 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { |
| 2061 EmitSmiComparisonOp(compiler, *locs(), kind(), this, | 2061 EmitSmiComparisonOp(compiler, *locs(), kind(), this, |
| 2062 cid(), token_pos(), try_index()); | 2062 deopt_id(), token_pos(), try_index()); |
| 2063 return; | 2063 return; |
| 2064 } | 2064 } |
| 2065 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { | 2065 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { |
| 2066 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, | 2066 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, |
| 2067 cid(), token_pos(), try_index()); | 2067 deopt_id(), token_pos(), try_index()); |
| 2068 return; | 2068 return; |
| 2069 } | 2069 } |
| 2070 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2070 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
| 2071 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2071 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| 2072 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2072 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), |
| 2073 cid(), token_pos(), try_index()); | 2073 deopt_id(), token_pos(), try_index()); |
| 2074 return; | 2074 return; |
| 2075 } | 2075 } |
| 2076 // Otherwise polymorphic dispatch? | 2076 // Otherwise polymorphic dispatch? |
| 2077 } | 2077 } |
| 2078 // Not equal is always split into '==' and negate, | 2078 // Not equal is always split into '==' and negate, |
| 2079 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 2079 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 2080 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); | 2080 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); |
| 2081 const String& function_name = | 2081 const String& function_name = |
| 2082 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); | 2082 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); |
| 2083 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2083 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 2084 cid(), | 2084 deopt_id(), |
| 2085 token_pos(), | 2085 token_pos(), |
| 2086 try_index()); | 2086 try_index()); |
| 2087 const intptr_t kNumArguments = 2; | 2087 const intptr_t kNumArguments = 2; |
| 2088 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2088 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 2089 compiler->GenerateInstanceCall(cid(), | 2089 compiler->GenerateInstanceCall(deopt_id(), |
| 2090 token_pos(), | 2090 token_pos(), |
| 2091 try_index(), | 2091 try_index(), |
| 2092 function_name, | 2092 function_name, |
| 2093 kNumArguments, | 2093 kNumArguments, |
| 2094 Array::ZoneHandle(), // No optional arguments. | 2094 Array::ZoneHandle(), // No optional arguments. |
| 2095 kNumArgsChecked); | 2095 kNumArgsChecked); |
| 2096 ASSERT(locs()->out().reg() == EAX); | 2096 ASSERT(locs()->out().reg() == EAX); |
| 2097 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2097 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
| 2098 EmitBranchOnCondition(compiler, branch_condition); | 2098 EmitBranchOnCondition(compiler, branch_condition); |
| 2099 } | 2099 } |
| 2100 | 2100 |
| 2101 } // namespace dart | 2101 } // namespace dart |
| 2102 | 2102 |
| 2103 #undef __ | 2103 #undef __ |
| 2104 | 2104 |
| 2105 #endif // defined TARGET_ARCH_X64 | 2105 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |