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

Side by Side Diff: src/codegen-ia32.cc

Issue 18144: Experimental: remove the cc_reg_ state from the code generator. There... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 74
75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, 75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script,
76 bool is_eval) 76 bool is_eval)
77 : is_eval_(is_eval), 77 : is_eval_(is_eval),
78 script_(script), 78 script_(script),
79 deferred_(8), 79 deferred_(8),
80 masm_(new MacroAssembler(NULL, buffer_size)), 80 masm_(new MacroAssembler(NULL, buffer_size)),
81 scope_(NULL), 81 scope_(NULL),
82 frame_(NULL), 82 frame_(NULL),
83 allocator_(NULL), 83 allocator_(NULL),
84 cc_reg_(no_condition),
85 state_(NULL), 84 state_(NULL),
86 break_stack_height_(0), 85 break_stack_height_(0),
87 loop_nesting_(0), 86 loop_nesting_(0),
88 function_return_is_shadowed_(false), 87 function_return_is_shadowed_(false),
89 in_spilled_code_(false) { 88 in_spilled_code_(false) {
90 } 89 }
91 90
92 91
93 void CodeGenerator::SetFrame(VirtualFrame* new_frame, 92 void CodeGenerator::SetFrame(VirtualFrame* new_frame,
94 RegisterFile* non_frame_registers) { 93 RegisterFile* non_frame_registers) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 ZoneList<Statement*>* body = fun->body(); 131 ZoneList<Statement*>* body = fun->body();
133 132
134 // Initialize state. 133 // Initialize state.
135 ASSERT(scope_ == NULL); 134 ASSERT(scope_ == NULL);
136 scope_ = fun->scope(); 135 scope_ = fun->scope();
137 ASSERT(allocator_ == NULL); 136 ASSERT(allocator_ == NULL);
138 RegisterAllocator register_allocator(this); 137 RegisterAllocator register_allocator(this);
139 allocator_ = &register_allocator; 138 allocator_ = &register_allocator;
140 ASSERT(frame_ == NULL); 139 ASSERT(frame_ == NULL);
141 frame_ = new VirtualFrame(this); 140 frame_ = new VirtualFrame(this);
142 cc_reg_ = no_condition;
143 function_return_.set_code_generator(this); 141 function_return_.set_code_generator(this);
144 function_return_is_shadowed_ = false; 142 function_return_is_shadowed_ = false;
145 set_in_spilled_code(false); 143 set_in_spilled_code(false);
146 144
147 // Adjust for function-level loop nesting. 145 // Adjust for function-level loop nesting.
148 loop_nesting_ += fun->loop_nesting(); 146 loop_nesting_ += fun->loop_nesting();
149 147
150 { 148 {
151 CodeGenState state(this); 149 CodeGenState state(this);
152 150
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 } 321 }
324 322
325 // Adjust for function-level loop nesting. 323 // Adjust for function-level loop nesting.
326 loop_nesting_ -= fun->loop_nesting(); 324 loop_nesting_ -= fun->loop_nesting();
327 325
328 // Code generation state must be reset. 326 // Code generation state must be reset.
329 ASSERT(state_ == NULL); 327 ASSERT(state_ == NULL);
330 ASSERT(loop_nesting() == 0); 328 ASSERT(loop_nesting() == 0);
331 ASSERT(!function_return_is_shadowed_); 329 ASSERT(!function_return_is_shadowed_);
332 function_return_.Unuse(); 330 function_return_.Unuse();
333 ASSERT(!has_cc());
334 DeleteFrame(); 331 DeleteFrame();
335 332
336 // Process any deferred code using the register allocator. 333 // Process any deferred code using the register allocator.
337 ProcessDeferred(); 334 ProcessDeferred();
338 335
339 // There is no need to delete the register allocator, it is a 336 // There is no need to delete the register allocator, it is a
340 // stack-allocated local. 337 // stack-allocated local.
341 allocator_ = NULL; 338 allocator_ = NULL;
342 scope_ = NULL; 339 scope_ = NULL;
343 } 340 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 return ContextOperand(tmp, index); 384 return ContextOperand(tmp, index);
388 } 385 }
389 386
390 default: 387 default:
391 UNREACHABLE(); 388 UNREACHABLE();
392 return Operand(eax); 389 return Operand(eax);
393 } 390 }
394 } 391 }
395 392
396 393
397 // Loads a value on TOS. If it is a boolean value, the result may have been 394 // Loads a value on TOS. If the result is a boolean value it may have
398 // (partially) translated into branches, or it may have set the condition 395 // been translated into control flow to the true and/or false targets.
399 // code register. If force_cc is set, the value is forced to set the 396 // If force_control is true, control flow is forced and the function
400 // condition code register and no value is pushed. If the condition code 397 // exits without a valid frame.
401 // register was set, has_cc() is true and cc_reg_ contains the condition to
402 // test for 'true'.
403 void CodeGenerator::LoadCondition(Expression* x, 398 void CodeGenerator::LoadCondition(Expression* x,
404 TypeofState typeof_state, 399 TypeofState typeof_state,
405 JumpTarget* true_target, 400 JumpTarget* true_target,
406 JumpTarget* false_target, 401 JumpTarget* false_target,
407 bool force_cc) { 402 bool force_control) {
408 ASSERT(!in_spilled_code()); 403 ASSERT(!in_spilled_code());
409 ASSERT(!has_cc());
410 #ifdef DEBUG 404 #ifdef DEBUG
411 int original_height = frame_->height(); 405 int original_height = frame_->height();
412 #endif 406 #endif
413 { CodeGenState new_state(this, typeof_state, true_target, false_target); 407 { CodeGenState new_state(this, typeof_state, true_target, false_target);
414 Visit(x); 408 Visit(x);
415 } 409 }
416 410
417 if (force_cc && has_valid_frame() && !has_cc()) { 411 if (force_control && has_valid_frame()) {
418 // Convert the TOS value to a boolean in the condition code register. 412 // Convert the TOS value to a boolean in the condition code register.
419 ToBoolean(true_target, false_target); 413 ToBoolean(true_target, false_target);
420 } 414 }
421 415
422 ASSERT(!force_cc || frame_ == NULL || has_cc()); 416 ASSERT(!(force_control && has_valid_frame()));
423 ASSERT(!has_valid_frame() || 417 ASSERT(!has_valid_frame() || frame_->height() == original_height + 1);
424 (has_cc() && frame_->height() == original_height) ||
425 (!has_cc() && frame_->height() == original_height + 1));
426 } 418 }
427 419
428 420
429 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { 421 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) {
430 #ifdef DEBUG 422 #ifdef DEBUG
431 int original_height = frame_->height(); 423 int original_height = frame_->height();
432 #endif 424 #endif
433 ASSERT(!in_spilled_code()); 425 ASSERT(!in_spilled_code());
434 JumpTarget true_target(this); 426 JumpTarget true_target(this);
435 JumpTarget false_target(this); 427 JumpTarget false_target(this);
436 LoadCondition(x, typeof_state, &true_target, &false_target, false); 428 LoadCondition(x, typeof_state, &true_target, &false_target, false);
437 429
438 if (has_cc()) {
439 ASSERT(has_valid_frame());
440 VirtualFrame::SpilledScope spilled_scope(this);
441 // Convert cc_reg_ into a boolean value.
442 JumpTarget loaded(this);
443 JumpTarget materialize_true(this);
444 Condition cc = cc_reg_;
445 cc_reg_ = no_condition;
446 materialize_true.Branch(cc);
447 frame_->EmitPush(Immediate(Factory::false_value()));
448 loaded.Jump();
449 materialize_true.Bind();
450 frame_->EmitPush(Immediate(Factory::true_value()));
451 loaded.Bind();
452 }
453
454 if (true_target.is_linked() || false_target.is_linked()) { 430 if (true_target.is_linked() || false_target.is_linked()) {
455 // We have at least one condition value that has been "translated" into 431 // We have at least one condition value that has been "translated" into
456 // a branch, thus it needs to be loaded explicitly. 432 // a branch, thus it needs to be loaded explicitly.
457 JumpTarget loaded(this); 433 JumpTarget loaded(this);
458 if (has_valid_frame()) { 434 if (has_valid_frame()) {
459 loaded.Jump(); // Don't lose the current TOS. 435 loaded.Jump(); // Don't lose the current TOS.
460 } 436 }
461 bool both = true_target.is_linked() && false_target.is_linked(); 437 bool both = true_target.is_linked() && false_target.is_linked();
462 // Load "true" if necessary. 438 // Load "true" if necessary.
463 if (true_target.is_linked()) { 439 if (true_target.is_linked()) {
464 true_target.Bind(); 440 true_target.Bind();
465 VirtualFrame::SpilledScope spilled_scope(this); 441 VirtualFrame::SpilledScope spilled_scope(this);
466 frame_->EmitPush(Immediate(Factory::true_value())); 442 frame_->EmitPush(Immediate(Factory::true_value()));
467 } 443 }
468 // If both "true" and "false" need to be reincarnated jump across the 444 // If both "true" and "false" need to be reincarnated jump across the
469 // code for "false". 445 // code for "false".
470 if (both) { 446 if (both) {
471 loaded.Jump(); 447 loaded.Jump();
472 } 448 }
473 // Load "false" if necessary. 449 // Load "false" if necessary.
474 if (false_target.is_linked()) { 450 if (false_target.is_linked()) {
475 false_target.Bind(); 451 false_target.Bind();
476 VirtualFrame::SpilledScope spilled_scope(this); 452 VirtualFrame::SpilledScope spilled_scope(this);
477 frame_->EmitPush(Immediate(Factory::false_value())); 453 frame_->EmitPush(Immediate(Factory::false_value()));
478 } 454 }
479 // A value is loaded on all paths reaching this point. 455 // A value is loaded on all paths reaching this point.
480 loaded.Bind(); 456 loaded.Bind();
481 } 457 }
482 ASSERT(has_valid_frame()); 458 ASSERT(has_valid_frame());
483 ASSERT(!has_cc());
484 ASSERT(frame_->height() == original_height + 1); 459 ASSERT(frame_->height() == original_height + 1);
485 } 460 }
486 461
487 462
488 void CodeGenerator::LoadGlobal() { 463 void CodeGenerator::LoadGlobal() {
489 if (in_spilled_code()) { 464 if (in_spilled_code()) {
490 frame_->EmitPush(GlobalObject()); 465 frame_->EmitPush(GlobalObject());
491 } else { 466 } else {
492 Result temp = allocator_->Allocate(); 467 Result temp = allocator_->Allocate();
493 __ mov(temp.reg(), GlobalObject()); 468 __ mov(temp.reg(), GlobalObject());
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 false_target->Branch(zero); 612 false_target->Branch(zero);
638 __ test(value.reg(), Immediate(kSmiTagMask)); 613 __ test(value.reg(), Immediate(kSmiTagMask));
639 true_target->Branch(zero); 614 true_target->Branch(zero);
640 615
641 // Call the stub for all other cases. 616 // Call the stub for all other cases.
642 frame_->Push(&value); // Undo the Pop() from above. 617 frame_->Push(&value); // Undo the Pop() from above.
643 ToBooleanStub stub; 618 ToBooleanStub stub;
644 Result temp = frame_->CallStub(&stub, 1); 619 Result temp = frame_->CallStub(&stub, 1);
645 // Convert the result to a condition code. 620 // Convert the result to a condition code.
646 __ test(temp.reg(), Operand(temp.reg())); 621 __ test(temp.reg(), Operand(temp.reg()));
647 622 temp.Unuse();
648 ASSERT(not_equal == not_zero); 623 true_target->Branch(not_equal);
649 cc_reg_ = not_equal; 624 false_target->Jump();
650 } 625 }
651 626
652 627
653 class FloatingPointHelper : public AllStatic { 628 class FloatingPointHelper : public AllStatic {
654 public: 629 public:
655 // Code pattern for loading floating point values. Input values must 630 // Code pattern for loading floating point values. Input values must
656 // be either smi or heap number objects (fp values). Requirements: 631 // be either smi or heap number objects (fp values). Requirements:
657 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as 632 // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as
658 // floating point numbers on FPU stack. 633 // floating point numbers on FPU stack.
659 static void LoadFloatOperands(MacroAssembler* masm, Register scratch); 634 static void LoadFloatOperands(MacroAssembler* masm, Register scratch);
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 #ifdef DEBUG 1173 #ifdef DEBUG
1199 void Print() { 1174 void Print() {
1200 PrintF("CompareStub (cc %d), (strict %s)\n", 1175 PrintF("CompareStub (cc %d), (strict %s)\n",
1201 static_cast<int>(cc_), 1176 static_cast<int>(cc_),
1202 strict_ ? "true" : "false"); 1177 strict_ ? "true" : "false");
1203 } 1178 }
1204 #endif 1179 #endif
1205 }; 1180 };
1206 1181
1207 1182
1208 void CodeGenerator::Comparison(Condition cc, bool strict) { 1183 void CodeGenerator::Comparison(Condition cc,
1184 bool strict,
1185 JumpTarget* true_target,
1186 JumpTarget* false_target) {
1209 // Strict only makes sense for equality comparisons. 1187 // Strict only makes sense for equality comparisons.
1210 ASSERT(!strict || cc == equal); 1188 ASSERT(!strict || cc == equal);
1211 1189
1212 Result left_side(this); 1190 Result left_side(this);
1213 Result right_side(this); 1191 Result right_side(this);
1214 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order. 1192 // Implement '>' and '<=' by reversal to obtain ECMA-262 conversion order.
1215 if (cc == greater || cc == less_equal) { 1193 if (cc == greater || cc == less_equal) {
1216 cc = ReverseCondition(cc); 1194 cc = ReverseCondition(cc);
1217 left_side = frame_->Pop(); 1195 left_side = frame_->Pop();
1218 right_side = frame_->Pop(); 1196 right_side = frame_->Pop();
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1284 } 1262 }
1285 __ cmp(left_side.reg(), Operand(right_side.reg())); 1263 __ cmp(left_side.reg(), Operand(right_side.reg()));
1286 right_side.Unuse(); 1264 right_side.Unuse();
1287 left_side.Unuse(); 1265 left_side.Unuse();
1288 __ setcc(cc, answer.reg()); 1266 __ setcc(cc, answer.reg());
1289 __ and_(Operand(answer.reg()), Immediate(1)); 1267 __ and_(Operand(answer.reg()), Immediate(1));
1290 1268
1291 done.Bind(&answer); 1269 done.Bind(&answer);
1292 answer.ToRegister(); 1270 answer.ToRegister();
1293 __ test(answer.reg(), Operand(answer.reg())); 1271 __ test(answer.reg(), Operand(answer.reg()));
1294 cc_reg_ = not_zero; 1272 answer.Unuse();
1273 true_target->Branch(not_zero);
1274 false_target->Jump();
1295 } 1275 }
1296 1276
1297 1277
1298 class DeferredSmiComparison: public DeferredCode { 1278 class DeferredSmiComparison: public DeferredCode {
1299 public: 1279 public:
1300 DeferredSmiComparison(CodeGenerator* generator, 1280 DeferredSmiComparison(CodeGenerator* generator,
1301 Condition cc, 1281 Condition cc,
1302 bool strict, 1282 bool strict,
1303 int int_value) : 1283 int int_value) :
1304 DeferredCode(generator), 1284 DeferredCode(generator),
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1367 } 1347 }
1368 // Test smi equality and comparison by signed int comparison. 1348 // Test smi equality and comparison by signed int comparison.
1369 __ cmp(Operand(comparee.reg()), Immediate(value)); 1349 __ cmp(Operand(comparee.reg()), Immediate(value));
1370 comparee.Unuse(); 1350 comparee.Unuse();
1371 __ setcc(cc, flag.reg()); 1351 __ setcc(cc, flag.reg());
1372 __ and_(Operand(flag.reg()), Immediate(1)); 1352 __ and_(Operand(flag.reg()), Immediate(1));
1373 1353
1374 deferred->exit()->Bind(&flag); 1354 deferred->exit()->Bind(&flag);
1375 flag.ToRegister(); 1355 flag.ToRegister();
1376 __ test(flag.reg(), Operand(flag.reg())); 1356 __ test(flag.reg(), Operand(flag.reg()));
1377 cc_reg_ = not_zero; 1357 flag.Unuse();
1358 true_target()->Branch(not_zero);
1359 false_target()->Jump();
1378 } 1360 }
1379 1361
1380 1362
1381 class CallFunctionStub: public CodeStub { 1363 class CallFunctionStub: public CodeStub {
1382 public: 1364 public:
1383 explicit CallFunctionStub(int argc) : argc_(argc) { } 1365 explicit CallFunctionStub(int argc) : argc_(argc) { }
1384 1366
1385 void Generate(MacroAssembler* masm); 1367 void Generate(MacroAssembler* masm);
1386 1368
1387 private: 1369 private:
(...skipping 24 matching lines...) Expand all
1412 // Use the shared code stub to call the function. 1394 // Use the shared code stub to call the function.
1413 CallFunctionStub call_function(arg_count); 1395 CallFunctionStub call_function(arg_count);
1414 Result answer = frame_->CallStub(&call_function, arg_count + 1); 1396 Result answer = frame_->CallStub(&call_function, arg_count + 1);
1415 // Restore context and replace function on the stack with the 1397 // Restore context and replace function on the stack with the
1416 // result of the stub invocation. 1398 // result of the stub invocation.
1417 frame_->RestoreContextRegister(); 1399 frame_->RestoreContextRegister();
1418 frame_->SetElementAt(0, &answer); 1400 frame_->SetElementAt(0, &answer);
1419 } 1401 }
1420 1402
1421 1403
1422 void CodeGenerator::Branch(bool if_true, JumpTarget* target) {
1423 ASSERT(has_cc());
1424 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_);
1425 cc_reg_ = no_condition;
1426 target->Branch(cc);
1427 }
1428
1429
1430 void CodeGenerator::CheckStack() { 1404 void CodeGenerator::CheckStack() {
1431 if (FLAG_check_stack) { 1405 if (FLAG_check_stack) {
1432 JumpTarget stack_is_ok(this); 1406 JumpTarget stack_is_ok(this);
1433 StackCheckStub stub; 1407 StackCheckStub stub;
1434 ExternalReference stack_guard_limit = 1408 ExternalReference stack_guard_limit =
1435 ExternalReference::address_of_stack_guard_limit(); 1409 ExternalReference::address_of_stack_guard_limit();
1436 __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 1410 __ cmp(esp, Operand::StaticVariable(stack_guard_limit));
1437 stack_is_ok.Branch(above_equal, taken); 1411 stack_is_ok.Branch(above_equal, taken);
1438 // The stack check can trigger the debugger. Before calling it, all 1412 // The stack check can trigger the debugger. Before calling it, all
1439 // values including constants must be spilled to the frame. 1413 // values including constants must be spilled to the frame.
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1566 // are present or not. 1540 // are present or not.
1567 bool has_then_stm = node->HasThenStatement(); 1541 bool has_then_stm = node->HasThenStatement();
1568 bool has_else_stm = node->HasElseStatement(); 1542 bool has_else_stm = node->HasElseStatement();
1569 1543
1570 CodeForStatement(node); 1544 CodeForStatement(node);
1571 JumpTarget exit(this); 1545 JumpTarget exit(this);
1572 if (has_then_stm && has_else_stm) { 1546 if (has_then_stm && has_else_stm) {
1573 JumpTarget then(this); 1547 JumpTarget then(this);
1574 JumpTarget else_(this); 1548 JumpTarget else_(this);
1575 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 1549 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
1576 if (has_valid_frame()) {
1577 // We have fallen through from the condition (with a value in cc_reg).
1578 // Emit a branch if false around the then block and compile both
1579 // blocks.
1580 Branch(false, &else_);
1581 }
1582 if (then.is_linked()) { 1550 if (then.is_linked()) {
1583 then.Bind(); 1551 then.Bind();
1584 }
1585 if (has_valid_frame()) {
1586 // We have fallen through from the condition or reached here by a
1587 // direct jump to the then target.
1588 Visit(node->then_statement()); 1552 Visit(node->then_statement());
1589 } 1553 if (has_valid_frame() && else_.is_linked()) {
1590 if (has_valid_frame() && else_.is_linked()) { 1554 // We have fallen through from the then block and we need to compile
1591 // We have fallen through from the then block and we need to compile 1555 // the else block. Emit an unconditional jump around it.
1592 // the else block. Emit an unconditional jump around it. 1556 exit.Jump();
1593 exit.Jump(); 1557 }
1594 } 1558 }
1595 if (else_.is_linked()) { 1559 if (else_.is_linked()) {
1596 else_.Bind(); 1560 else_.Bind();
1597 Visit(node->else_statement()); 1561 Visit(node->else_statement());
1598 } 1562 }
1599 1563
1600 } else if (has_then_stm) { 1564 } else if (has_then_stm) {
1601 ASSERT(!has_else_stm); 1565 ASSERT(!has_else_stm);
1602 JumpTarget then(this); 1566 JumpTarget then(this);
1603 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true); 1567 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &exit, true);
1604 if (has_valid_frame()) {
1605 // We have fallen through from the condition (with a value in cc_reg).
1606 // Emit a branch if false around the then block.
1607 Branch(false, &exit);
1608 }
1609 if (then.is_linked()) { 1568 if (then.is_linked()) {
1610 then.Bind(); 1569 then.Bind();
1611 }
1612 if (has_valid_frame()) {
1613 // We have fallen through from the condition or reached here by a
1614 // direct jump to the then target.
1615 Visit(node->then_statement()); 1570 Visit(node->then_statement());
1616 } 1571 }
1617 1572
1618 } else if (has_else_stm) { 1573 } else if (has_else_stm) {
1619 ASSERT(!has_then_stm); 1574 ASSERT(!has_then_stm);
1620 JumpTarget else_(this); 1575 JumpTarget else_(this);
1621 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true); 1576 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &else_, true);
1622 if (has_valid_frame()) {
1623 // We have fallen through from the condition (with a value in cc_reg).
1624 // Emit a branch if true around the else block.
1625 Branch(true, &exit);
1626 }
1627 if (else_.is_linked()) { 1577 if (else_.is_linked()) {
1628 else_.Bind(); 1578 else_.Bind();
1629 }
1630 if (has_valid_frame()) {
1631 // We have fallen through from the condition or reached here by a
1632 // direct jump to the else target.
1633 Visit(node->else_statement()); 1579 Visit(node->else_statement());
1634 } 1580 }
1635 1581
1636 } else { 1582 } else {
1637 ASSERT(!has_then_stm && !has_else_stm); 1583 ASSERT(!has_then_stm && !has_else_stm);
1638 // We only care about the condition's side effects (not its value or 1584 // We only care about the condition's side effects (not its value
1639 // control flow effect). LoadCondition is called without forcing a 1585 // or control flow effect). LoadCondition is called without
1640 // value into cc_reg. 1586 // forcing control flow.
1641 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false); 1587 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &exit, &exit, false);
1642 if (has_valid_frame()) { 1588 if (has_valid_frame()) {
1643 // Control flow can fall off the end of the condition. We discard its 1589 // Control flow can fall off the end of the condition with a
1644 // value, which may be in cc_reg or else on top of the virtual frame. 1590 // value on the frame.
1645 if (has_cc()) { 1591 frame_->Drop();
1646 cc_reg_ = no_condition;
1647 } else {
1648 frame_->Drop();
1649 }
1650 } 1592 }
1651 } 1593 }
1652 1594
1653 if (exit.is_linked()) { 1595 if (exit.is_linked()) {
1654 exit.Bind(); 1596 exit.Bind();
1655 } 1597 }
1656 } 1598 }
1657 1599
1658 1600
1659 void CodeGenerator::CleanStack(int num_bytes) { 1601 void CodeGenerator::CleanStack(int num_bytes) {
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 Comment cmnt(masm_, "[ Case clause"); 1841 Comment cmnt(masm_, "[ Case clause");
1900 // Label and compile the test. 1842 // Label and compile the test.
1901 if (next_test.is_linked()) { 1843 if (next_test.is_linked()) {
1902 // Recycle the same label for each test. 1844 // Recycle the same label for each test.
1903 next_test.Bind(); 1845 next_test.Bind();
1904 next_test.Unuse(); 1846 next_test.Unuse();
1905 } 1847 }
1906 // Duplicate the switch value. 1848 // Duplicate the switch value.
1907 frame_->Dup(); 1849 frame_->Dup();
1908 Load(clause->label()); 1850 Load(clause->label());
1909 Comparison(equal, true); 1851 JumpTarget enter_body(this);
1910 Branch(false, &next_test); 1852 Comparison(equal, true, &enter_body, &next_test);
1911 1853
1912 // Before entering the body from the test remove the switch value from 1854 // Before entering the body from the test remove the switch value from
1913 // the frame. 1855 // the frame.
1856 enter_body.Bind();
1914 frame_->Drop(); 1857 frame_->Drop();
1915 1858
1916 // Label the body so that fall through is enabled. 1859 // Label the body so that fall through is enabled.
1917 if (i > 0 && cases->at(i - 1)->is_default()) { 1860 if (i > 0 && cases->at(i - 1)->is_default()) {
1918 // The previous case was the default. This will be the target of a 1861 // The previous case was the default. This will be the target of a
1919 // possible backward edge. 1862 // possible backward edge.
1920 default_exit.Bind(); 1863 default_exit.Bind();
1921 } else if (fall_through.is_linked()) { 1864 } else if (fall_through.is_linked()) {
1922 // Recycle the same label for each fall through except for the default 1865 // Recycle the same label for each fall through except for the default
1923 // case. 1866 // case.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2024 } else { 1967 } else {
2025 ASSERT(info == DONT_KNOW); 1968 ASSERT(info == DONT_KNOW);
2026 // We have to compile the test expression if it can be reached by 1969 // We have to compile the test expression if it can be reached by
2027 // control flow falling out of the body or via continue. 1970 // control flow falling out of the body or via continue.
2028 if (node->continue_target()->is_linked()) { 1971 if (node->continue_target()->is_linked()) {
2029 node->continue_target()->Bind(); 1972 node->continue_target()->Bind();
2030 } 1973 }
2031 if (has_valid_frame()) { 1974 if (has_valid_frame()) {
2032 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 1975 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
2033 &body, node->break_target(), true); 1976 &body, node->break_target(), true);
2034 // An invalid frame here indicates that control flow did not fall
2035 // out of the test expression.
2036 if (has_valid_frame()) {
2037 Branch(true, &body);
2038 }
2039 } 1977 }
2040 } 1978 }
2041 break; 1979 break;
2042 } 1980 }
2043 1981
2044 case LoopStatement::WHILE_LOOP: { 1982 case LoopStatement::WHILE_LOOP: {
2045 IncrementLoopNesting(); 1983 IncrementLoopNesting();
2046 1984
2047 // If the test is never true and has no side effects there is no need 1985 // If the test is never true and has no side effects there is no need
2048 // to compile the test or body. 1986 // to compile the test or body.
2049 if (info == ALWAYS_FALSE) break; 1987 if (info == ALWAYS_FALSE) break;
2050 1988
2051 // Label the top of the loop with the continue target for the backward 1989 // Label the top of the loop with the continue target for the backward
2052 // CFG edge. 1990 // CFG edge.
2053 node->continue_target()->Bind(); 1991 node->continue_target()->Bind();
2054 1992
2055 // If the test is always true and has no side effects there is no need 1993 // If the test is always true and has no side effects there is no need
2056 // to compile it. We only compile the test when we do not know its 1994 // to compile it. We only compile the test when we do not know its
2057 // outcome or it may have side effects. 1995 // outcome or it may have side effects.
2058 if (info == DONT_KNOW) { 1996 if (info == DONT_KNOW) {
2059 JumpTarget body(this); 1997 JumpTarget body(this);
2060 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 1998 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
2061 &body, node->break_target(), true); 1999 &body, node->break_target(), true);
2062 // An invalid frame indicates that control did not fall out of the
2063 // test expression.
2064 if (has_valid_frame()) {
2065 Branch(false, node->break_target());
2066 }
2067 if (body.is_linked()) { 2000 if (body.is_linked()) {
2068 body.Bind(); 2001 body.Bind();
2069 } 2002 }
2070 } 2003 }
2071 2004
2072 if (has_valid_frame()) { 2005 if (has_valid_frame()) {
2073 CheckStack(); // TODO(1222600): ignore if body contains calls. 2006 CheckStack(); // TODO(1222600): ignore if body contains calls.
2074 Visit(node->body()); 2007 Visit(node->body());
2075 2008
2076 // If control flow can fall out of the body, jump back to the top. 2009 // If control flow can fall out of the body, jump back to the top.
(...skipping 23 matching lines...) Expand all
2100 loop.Bind(); 2033 loop.Bind();
2101 } 2034 }
2102 2035
2103 // If the test is always true and has no side effects there is no need 2036 // If the test is always true and has no side effects there is no need
2104 // to compile it. We only compile the test when we do not know its 2037 // to compile it. We only compile the test when we do not know its
2105 // outcome or it has side effects. 2038 // outcome or it has side effects.
2106 if (info == DONT_KNOW) { 2039 if (info == DONT_KNOW) {
2107 JumpTarget body(this); 2040 JumpTarget body(this);
2108 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, 2041 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF,
2109 &body, node->break_target(), true); 2042 &body, node->break_target(), true);
2110 if (has_valid_frame()) {
2111 Branch(false, node->break_target());
2112 }
2113 if (body.is_linked()) { 2043 if (body.is_linked()) {
2114 body.Bind(); 2044 body.Bind();
2115 } 2045 }
2116 } 2046 }
2117 2047
2118 if (has_valid_frame()) { 2048 if (has_valid_frame()) {
2119 CheckStack(); // TODO(1222600): ignore if body contains calls. 2049 CheckStack(); // TODO(1222600): ignore if body contains calls.
2120 Visit(node->body()); 2050 Visit(node->body());
2121 2051
2122 if (node->next() == NULL) { 2052 if (node->next() == NULL) {
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after
2685 InstantiateBoilerplate(node->boilerplate()); 2615 InstantiateBoilerplate(node->boilerplate());
2686 } 2616 }
2687 2617
2688 2618
2689 void CodeGenerator::VisitConditional(Conditional* node) { 2619 void CodeGenerator::VisitConditional(Conditional* node) {
2690 Comment cmnt(masm_, "[ Conditional"); 2620 Comment cmnt(masm_, "[ Conditional");
2691 JumpTarget then(this); 2621 JumpTarget then(this);
2692 JumpTarget else_(this); 2622 JumpTarget else_(this);
2693 JumpTarget exit(this); 2623 JumpTarget exit(this);
2694 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true); 2624 LoadCondition(node->condition(), NOT_INSIDE_TYPEOF, &then, &else_, true);
2695 if (has_valid_frame()) {
2696 Branch(false, &else_);
2697 }
2698 if (then.is_linked()) { 2625 if (then.is_linked()) {
2699 then.Bind(); 2626 then.Bind();
2627 Load(node->then_expression(), typeof_state());
2628 if (else_.is_linked()) {
2629 exit.Jump();
2630 }
2700 } 2631 }
2701 if (has_valid_frame()) { 2632
2702 Load(node->then_expression(), typeof_state());
2703 exit.Jump();
2704 }
2705 if (else_.is_linked()) { 2633 if (else_.is_linked()) {
2706 else_.Bind(); 2634 else_.Bind();
2707 Load(node->else_expression(), typeof_state()); 2635 Load(node->else_expression(), typeof_state());
2708 } 2636 }
2709 exit.Bind(); 2637
2638 if (exit.is_linked()) {
2639 exit.Bind();
2640 }
2710 } 2641 }
2711 2642
2712 2643
2713 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { 2644 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) {
2714 if (slot->type() == Slot::LOOKUP) { 2645 if (slot->type() == Slot::LOOKUP) {
2715 ASSERT(slot->var()->mode() == Variable::DYNAMIC); 2646 ASSERT(slot->var()->mode() == Variable::DYNAMIC);
2716 2647
2717 // For now, just do a runtime call. 2648 // For now, just do a runtime call.
2718 frame_->Push(esi); 2649 frame_->Push(esi);
2719 frame_->Push(slot->var()->name()); 2650 frame_->Push(slot->var()->name());
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
3451 frame_->RestoreContextRegister(); 3382 frame_->RestoreContextRegister();
3452 __ mov(frame_->Top(), eax); 3383 __ mov(frame_->Top(), eax);
3453 } 3384 }
3454 3385
3455 3386
3456 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3387 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3457 ASSERT(args->length() == 1); 3388 ASSERT(args->length() == 1);
3458 LoadAndSpill(args->at(0)); 3389 LoadAndSpill(args->at(0));
3459 frame_->EmitPop(eax); 3390 frame_->EmitPop(eax);
3460 __ test(eax, Immediate(kSmiTagMask)); 3391 __ test(eax, Immediate(kSmiTagMask));
3461 cc_reg_ = zero; 3392 true_target()->Branch(zero);
3393 false_target()->Jump();
3462 } 3394 }
3463 3395
3464 3396
3465 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { 3397 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) {
3466 // Conditionally generate a log call. 3398 // Conditionally generate a log call.
3467 // Args: 3399 // Args:
3468 // 0 (literal string): The type of logging (corresponds to the flags). 3400 // 0 (literal string): The type of logging (corresponds to the flags).
3469 // This is used to determine whether or not to generate the log call. 3401 // This is used to determine whether or not to generate the log call.
3470 // 1 (string): Format string. Access the string at argument index 2 3402 // 1 (string): Format string. Access the string at argument index 2
3471 // with '%2s' (see Logger::LogRuntime for all the formats). 3403 // with '%2s' (see Logger::LogRuntime for all the formats).
3472 // 2 (array): Arguments to the format string. 3404 // 2 (array): Arguments to the format string.
3473 ASSERT_EQ(args->length(), 3); 3405 ASSERT_EQ(args->length(), 3);
3474 #ifdef ENABLE_LOGGING_AND_PROFILING 3406 #ifdef ENABLE_LOGGING_AND_PROFILING
3475 if (ShouldGenerateLog(args->at(0))) { 3407 if (ShouldGenerateLog(args->at(0))) {
3476 LoadAndSpill(args->at(1)); 3408 LoadAndSpill(args->at(1));
3477 LoadAndSpill(args->at(2)); 3409 LoadAndSpill(args->at(2));
3478 frame_->CallRuntime(Runtime::kLog, 2); 3410 frame_->CallRuntime(Runtime::kLog, 2);
3479 } 3411 }
3480 #endif 3412 #endif
3481 // Finally, we're expected to leave a value on the top of the stack. 3413 // Finally, we're expected to leave a value on the top of the stack.
3482 frame_->EmitPush(Immediate(Factory::undefined_value())); 3414 frame_->EmitPush(Immediate(Factory::undefined_value()));
3483 } 3415 }
3484 3416
3485 3417
3486 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3418 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3487 ASSERT(args->length() == 1); 3419 ASSERT(args->length() == 1);
3488 LoadAndSpill(args->at(0)); 3420 LoadAndSpill(args->at(0));
3489 frame_->EmitPop(eax); 3421 frame_->EmitPop(eax);
3490 __ test(eax, Immediate(kSmiTagMask | 0x80000000)); 3422 __ test(eax, Immediate(kSmiTagMask | 0x80000000));
3491 cc_reg_ = zero; 3423 true_target()->Branch(zero);
3424 false_target()->Jump();
3492 } 3425 }
3493 3426
3494 3427
3495 // This generates code that performs a charCodeAt() call or returns 3428 // This generates code that performs a charCodeAt() call or returns
3496 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3429 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3497 // It can handle flat and sliced strings, 8 and 16 bit characters and 3430 // It can handle flat and sliced strings, 8 and 16 bit characters and
3498 // cons strings where the answer is found in the left hand branch of the 3431 // cons strings where the answer is found in the left hand branch of the
3499 // cons. The slow case will flatten the string, which will ensure that 3432 // cons. The slow case will flatten the string, which will ensure that
3500 // the answer is in the left hand side the next time around. 3433 // the answer is in the left hand side the next time around.
3501 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3434 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3605 slow_case.Bind(); 3538 slow_case.Bind();
3606 frame_->EmitPush(Immediate(Factory::undefined_value())); 3539 frame_->EmitPush(Immediate(Factory::undefined_value()));
3607 3540
3608 end.Bind(); 3541 end.Bind();
3609 } 3542 }
3610 3543
3611 3544
3612 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3545 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3613 ASSERT(args->length() == 1); 3546 ASSERT(args->length() == 1);
3614 LoadAndSpill(args->at(0)); 3547 LoadAndSpill(args->at(0));
3615 Label answer;
3616 // We need the CC bits to come out as not_equal in the case where the 3548 // We need the CC bits to come out as not_equal in the case where the
3617 // object is a smi. This can't be done with the usual test opcode so 3549 // object is a smi. This can't be done with the usual test opcode so
3618 // we copy the object to ecx and do some destructive ops on it that 3550 // we copy the object to ecx and do some destructive ops on it that
3619 // result in the right CC bits. 3551 // result in the right CC bits.
3620 frame_->EmitPop(eax); 3552 frame_->EmitPop(eax);
3621 __ mov(ecx, Operand(eax)); 3553 __ mov(ecx, Operand(eax));
3622 __ and_(ecx, kSmiTagMask); 3554 __ and_(ecx, kSmiTagMask);
3623 __ xor_(ecx, kSmiTagMask); 3555 __ xor_(ecx, kSmiTagMask);
3624 __ j(not_equal, &answer, not_taken); 3556 false_target()->Branch(not_equal);
3625 // It is a heap object - get map. 3557 // It is a heap object - get map.
3626 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 3558 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
3627 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset)); 3559 __ movzx_b(eax, FieldOperand(eax, Map::kInstanceTypeOffset));
3628 // Check if the object is a JS array or not. 3560 // Check if the object is a JS array or not.
3629 __ cmp(eax, JS_ARRAY_TYPE); 3561 __ cmp(eax, JS_ARRAY_TYPE);
3630 __ bind(&answer); 3562 true_target()->Branch(equal);
3631 cc_reg_ = equal; 3563 false_target()->Jump();
3632 } 3564 }
3633 3565
3634 3566
3635 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 3567 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
3636 ASSERT(args->length() == 0); 3568 ASSERT(args->length() == 0);
3637 3569
3638 // Seed the result with the formal parameters count, which will be 3570 // Seed the result with the formal parameters count, which will be
3639 // used in case no arguments adaptor frame is found below the 3571 // used in case no arguments adaptor frame is found below the
3640 // current frame. 3572 // current frame.
3641 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters()))); 3573 __ Set(eax, Immediate(Smi::FromInt(scope_->num_parameters())));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3712 3644
3713 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 3645 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
3714 ASSERT(args->length() == 2); 3646 ASSERT(args->length() == 2);
3715 3647
3716 // Load the two objects into registers and perform the comparison. 3648 // Load the two objects into registers and perform the comparison.
3717 LoadAndSpill(args->at(0)); 3649 LoadAndSpill(args->at(0));
3718 LoadAndSpill(args->at(1)); 3650 LoadAndSpill(args->at(1));
3719 frame_->EmitPop(eax); 3651 frame_->EmitPop(eax);
3720 frame_->EmitPop(ecx); 3652 frame_->EmitPop(ecx);
3721 __ cmp(eax, Operand(ecx)); 3653 __ cmp(eax, Operand(ecx));
3722 cc_reg_ = equal; 3654 true_target()->Branch(equal);
3655 false_target()->Jump();
3723 } 3656 }
3724 3657
3725 3658
3726 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 3659 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
3727 VirtualFrame::SpilledScope spilled_scope(this); 3660 VirtualFrame::SpilledScope spilled_scope(this);
3728 if (CheckForInlineRuntimeCall(node)) { 3661 if (CheckForInlineRuntimeCall(node)) {
3729 return; 3662 return;
3730 } 3663 }
3731 3664
3732 ZoneList<Expression*>* args = node->arguments(); 3665 ZoneList<Expression*>* args = node->arguments();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3767 // expression to a literal string, this function can fail to leave a value 3700 // expression to a literal string, this function can fail to leave a value
3768 // on top of the frame or in the cc register. 3701 // on top of the frame or in the cc register.
3769 Comment cmnt(masm_, "[ UnaryOperation"); 3702 Comment cmnt(masm_, "[ UnaryOperation");
3770 3703
3771 Token::Value op = node->op(); 3704 Token::Value op = node->op();
3772 3705
3773 if (op == Token::NOT) { 3706 if (op == Token::NOT) {
3774 VirtualFrame::SpilledScope spilled_scope(this); 3707 VirtualFrame::SpilledScope spilled_scope(this);
3775 LoadConditionAndSpill(node->expression(), NOT_INSIDE_TYPEOF, 3708 LoadConditionAndSpill(node->expression(), NOT_INSIDE_TYPEOF,
3776 false_target(), true_target(), true); 3709 false_target(), true_target(), true);
3777 cc_reg_ = NegateCondition(cc_reg_);
3778 3710
3779 } else if (op == Token::DELETE) { 3711 } else if (op == Token::DELETE) {
3780 VirtualFrame::SpilledScope spilled_scope(this); 3712 VirtualFrame::SpilledScope spilled_scope(this);
3781 Property* property = node->expression()->AsProperty(); 3713 Property* property = node->expression()->AsProperty();
3782 if (property != NULL) { 3714 if (property != NULL) {
3783 LoadAndSpill(property->obj()); 3715 LoadAndSpill(property->obj());
3784 LoadAndSpill(property->key()); 3716 LoadAndSpill(property->key());
3785 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2); 3717 frame_->InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION, 2);
3786 frame_->EmitPush(eax); 3718 frame_->EmitPush(eax);
3787 return; 3719 return;
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
4102 // the CC register), we force the right hand side to do the 4034 // the CC register), we force the right hand side to do the
4103 // same. This is necessary because we may have to branch to the exit 4035 // same. This is necessary because we may have to branch to the exit
4104 // after evaluating the left hand side (due to the shortcut 4036 // after evaluating the left hand side (due to the shortcut
4105 // semantics), but the compiler must (statically) know if the result 4037 // semantics), but the compiler must (statically) know if the result
4106 // of compiling the binary operation is materialized or not. 4038 // of compiling the binary operation is materialized or not.
4107 4039
4108 if (op == Token::AND) { 4040 if (op == Token::AND) {
4109 JumpTarget is_true(this); 4041 JumpTarget is_true(this);
4110 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, 4042 LoadCondition(node->left(), NOT_INSIDE_TYPEOF,
4111 &is_true, false_target(), false); 4043 &is_true, false_target(), false);
4112 if (has_cc() || frame_ == NULL) { 4044 if (!has_valid_frame()) {
4113 if (has_cc()) {
4114 ASSERT(has_valid_frame());
4115 Branch(false, false_target());
4116 }
4117
4118 if (is_true.is_linked()) { 4045 if (is_true.is_linked()) {
4046 // Evaluate right side expression.
4119 is_true.Bind(); 4047 is_true.Bind();
4120 }
4121 if (has_valid_frame()) {
4122 // Evaluate right side expression.
4123 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, 4048 LoadCondition(node->right(), NOT_INSIDE_TYPEOF,
4124 true_target(), false_target(), false); 4049 true_target(), false_target(), false);
4125 } 4050 }
4126 } else { 4051 } else {
4127 // We have a materialized value on the frame. 4052 // We have a materialized value on the frame.
4128 JumpTarget pop_and_continue(this); 4053 JumpTarget pop_and_continue(this);
4129 JumpTarget exit(this); 4054 JumpTarget exit(this);
4130 4055
4131 // Avoid popping the result if it converts to 'false' using the 4056 // Avoid popping the result if it converts to 'false' using the
4132 // standard ToBoolean() conversion as described in ECMA-262, section 4057 // standard ToBoolean() conversion as described in ECMA-262, section
4133 // 9.2, page 30. 4058 // 9.2, page 30.
4134 // 4059 //
4135 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 4060 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
4136 frame_->Dup(); 4061 frame_->Dup();
4137 ToBoolean(&pop_and_continue, &exit); 4062 ToBoolean(&pop_and_continue, &exit);
4138 Branch(false, &exit);
4139 4063
4140 // Pop the result of evaluating the first part. 4064 // Pop the result of evaluating the first part.
4141 pop_and_continue.Bind(); 4065 pop_and_continue.Bind();
4142 frame_->Drop(); 4066 frame_->Drop();
4143 4067
4144 // Evaluate right side expression. 4068 // Evaluate right side expression.
4145 is_true.Bind(); 4069 is_true.Bind();
4146 Load(node->right()); 4070 Load(node->right());
4147 4071
4148 // Exit (always with a materialized value). 4072 // Exit (always with a materialized value).
4149 exit.Bind(); 4073 exit.Bind();
4150 } 4074 }
4151 4075
4152 } else if (op == Token::OR) { 4076 } else if (op == Token::OR) {
4153 JumpTarget is_false(this); 4077 JumpTarget is_false(this);
4154 LoadCondition(node->left(), NOT_INSIDE_TYPEOF, 4078 LoadCondition(node->left(), NOT_INSIDE_TYPEOF,
4155 true_target(), &is_false, false); 4079 true_target(), &is_false, false);
4156 if (has_cc() || frame_ == NULL) { 4080 if (!has_valid_frame()) {
4157 if (has_cc()) {
4158 ASSERT(has_valid_frame());
4159 Branch(true, true_target());
4160 }
4161
4162 if (is_false.is_linked()) { 4081 if (is_false.is_linked()) {
4163 // Evaluate right side expression. 4082 // Evaluate right side expression.
4164 is_false.Bind(); 4083 is_false.Bind();
4165 }
4166 if (has_valid_frame()) {
4167 LoadCondition(node->right(), NOT_INSIDE_TYPEOF, 4084 LoadCondition(node->right(), NOT_INSIDE_TYPEOF,
4168 true_target(), false_target(), false); 4085 true_target(), false_target(), false);
4169 } 4086 }
4170 } else { 4087 } else {
4171 // We have a materialized value on the frame. 4088 // We have a materialized value on the frame.
4172 JumpTarget pop_and_continue(this); 4089 JumpTarget pop_and_continue(this);
4173 JumpTarget exit(this); 4090 JumpTarget exit(this);
4174 4091
4175 // Avoid popping the result if it converts to 'true' using the 4092 // Avoid popping the result if it converts to 'true' using the
4176 // standard ToBoolean() conversion as described in ECMA-262, 4093 // standard ToBoolean() conversion as described in ECMA-262,
4177 // section 9.2, page 30. 4094 // section 9.2, page 30.
4178 // Duplicate the TOS value. The duplicate will be popped by ToBoolean. 4095 // Duplicate the TOS value. The duplicate will be popped by ToBoolean.
4179 frame_->Dup(); 4096 frame_->Dup();
4180 ToBoolean(&exit, &pop_and_continue); 4097 ToBoolean(&exit, &pop_and_continue);
4181 Branch(true, &exit);
4182 4098
4183 // Pop the result of evaluating the first part. 4099 // Pop the result of evaluating the first part.
4184 pop_and_continue.Bind(); 4100 pop_and_continue.Bind();
4185 frame_->Drop(); 4101 frame_->Drop();
4186 4102
4187 // Evaluate right side expression. 4103 // Evaluate right side expression.
4188 is_false.Bind(); 4104 is_false.Bind();
4189 Load(node->right()); 4105 Load(node->right());
4190 4106
4191 // Exit (always with a materialized value). 4107 // Exit (always with a materialized value).
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
4279 __ test(eax, Immediate(kSmiTagMask)); 4195 __ test(eax, Immediate(kSmiTagMask));
4280 false_target()->Branch(equal); 4196 false_target()->Branch(equal);
4281 4197
4282 // It can be an undetectable object. 4198 // It can be an undetectable object.
4283 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); 4199 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
4284 __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset)); 4200 __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
4285 __ and_(eax, 1 << Map::kIsUndetectable); 4201 __ and_(eax, 1 << Map::kIsUndetectable);
4286 __ cmp(eax, 1 << Map::kIsUndetectable); 4202 __ cmp(eax, 1 << Map::kIsUndetectable);
4287 } 4203 }
4288 4204
4289 cc_reg_ = equal; 4205 true_target()->Branch(equal);
4206 false_target()->Jump();
4290 return; 4207 return;
4291 } 4208 }
4292 } 4209 }
4293 4210
4294 // To make typeof testing for natives implemented in JavaScript really 4211 // To make typeof testing for natives implemented in JavaScript really
4295 // efficient, we generate special code for expressions of the form: 4212 // efficient, we generate special code for expressions of the form:
4296 // 'typeof <expression> == <string>'. 4213 // 'typeof <expression> == <string>'.
4297 UnaryOperation* operation = left->AsUnaryOperation(); 4214 UnaryOperation* operation = left->AsUnaryOperation();
4298 if ((op == Token::EQ || op == Token::EQ_STRICT) && 4215 if ((op == Token::EQ || op == Token::EQ_STRICT) &&
4299 (operation != NULL && operation->op() == Token::TYPEOF) && 4216 (operation != NULL && operation->op() == Token::TYPEOF) &&
4300 (right->AsLiteral() != NULL && 4217 (right->AsLiteral() != NULL &&
4301 right->AsLiteral()->handle()->IsString())) { 4218 right->AsLiteral()->handle()->IsString())) {
4302 Handle<String> check(String::cast(*right->AsLiteral()->handle())); 4219 Handle<String> check(String::cast(*right->AsLiteral()->handle()));
4303 4220
4304 VirtualFrame::SpilledScope spilled_scope(this); 4221 VirtualFrame::SpilledScope spilled_scope(this);
4305 // Load the operand and move it to register edx. 4222 // Load the operand and move it to register edx.
4306 LoadTypeofExpression(operation->expression()); 4223 LoadTypeofExpression(operation->expression());
4307 frame_->EmitPop(edx); 4224 frame_->EmitPop(edx);
4308 4225
4309 if (check->Equals(Heap::number_symbol())) { 4226 if (check->Equals(Heap::number_symbol())) {
4310 __ test(edx, Immediate(kSmiTagMask)); 4227 __ test(edx, Immediate(kSmiTagMask));
4311 true_target()->Branch(zero); 4228 true_target()->Branch(zero);
4312 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4229 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
4313 __ cmp(edx, Factory::heap_number_map()); 4230 __ cmp(edx, Factory::heap_number_map());
4314 cc_reg_ = equal; 4231 true_target()->Branch(equal);
4232 false_target()->Jump();
4315 4233
4316 } else if (check->Equals(Heap::string_symbol())) { 4234 } else if (check->Equals(Heap::string_symbol())) {
4317 __ test(edx, Immediate(kSmiTagMask)); 4235 __ test(edx, Immediate(kSmiTagMask));
4318 false_target()->Branch(zero); 4236 false_target()->Branch(zero);
4319 4237
4320 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4238 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
4321 4239
4322 // It can be an undetectable string object. 4240 // It can be an undetectable string object.
4323 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 4241 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
4324 __ and_(ecx, 1 << Map::kIsUndetectable); 4242 __ and_(ecx, 1 << Map::kIsUndetectable);
4325 __ cmp(ecx, 1 << Map::kIsUndetectable); 4243 __ cmp(ecx, 1 << Map::kIsUndetectable);
4326 false_target()->Branch(equal); 4244 false_target()->Branch(equal);
4327 4245
4328 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset)); 4246 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
4329 __ cmp(ecx, FIRST_NONSTRING_TYPE); 4247 __ cmp(ecx, FIRST_NONSTRING_TYPE);
4330 cc_reg_ = less; 4248 true_target()->Branch(less);
4249 false_target()->Jump();
4331 4250
4332 } else if (check->Equals(Heap::boolean_symbol())) { 4251 } else if (check->Equals(Heap::boolean_symbol())) {
4333 __ cmp(edx, Factory::true_value()); 4252 __ cmp(edx, Factory::true_value());
4334 true_target()->Branch(equal); 4253 true_target()->Branch(equal);
4335 __ cmp(edx, Factory::false_value()); 4254 __ cmp(edx, Factory::false_value());
4336 cc_reg_ = equal; 4255 true_target()->Branch(equal);
4256 false_target()->Jump();
4337 4257
4338 } else if (check->Equals(Heap::undefined_symbol())) { 4258 } else if (check->Equals(Heap::undefined_symbol())) {
4339 __ cmp(edx, Factory::undefined_value()); 4259 __ cmp(edx, Factory::undefined_value());
4340 true_target()->Branch(equal); 4260 true_target()->Branch(equal);
4341 4261
4342 __ test(edx, Immediate(kSmiTagMask)); 4262 __ test(edx, Immediate(kSmiTagMask));
4343 false_target()->Branch(zero); 4263 false_target()->Branch(zero);
4344 4264
4345 // It can be an undetectable object. 4265 // It can be an undetectable object.
4346 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4266 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
4347 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 4267 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
4348 __ and_(ecx, 1 << Map::kIsUndetectable); 4268 __ and_(ecx, 1 << Map::kIsUndetectable);
4349 __ cmp(ecx, 1 << Map::kIsUndetectable); 4269 __ cmp(ecx, 1 << Map::kIsUndetectable);
4350 4270 true_target()->Branch(equal);
4351 cc_reg_ = equal; 4271 false_target()->Jump();
4352 4272
4353 } else if (check->Equals(Heap::function_symbol())) { 4273 } else if (check->Equals(Heap::function_symbol())) {
4354 __ test(edx, Immediate(kSmiTagMask)); 4274 __ test(edx, Immediate(kSmiTagMask));
4355 false_target()->Branch(zero); 4275 false_target()->Branch(zero);
4356 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset)); 4276 __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
4357 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset)); 4277 __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
4358 __ cmp(edx, JS_FUNCTION_TYPE); 4278 __ cmp(edx, JS_FUNCTION_TYPE);
4359 cc_reg_ = equal; 4279 true_target()->Branch(equal);
4280 false_target()->Jump();
4360 4281
4361 } else if (check->Equals(Heap::object_symbol())) { 4282 } else if (check->Equals(Heap::object_symbol())) {
4362 __ test(edx, Immediate(kSmiTagMask)); 4283 __ test(edx, Immediate(kSmiTagMask));
4363 false_target()->Branch(zero); 4284 false_target()->Branch(zero);
4364 4285
4365 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 4286 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
4366 __ cmp(edx, Factory::null_value()); 4287 __ cmp(edx, Factory::null_value());
4367 true_target()->Branch(equal); 4288 true_target()->Branch(equal);
4368 4289
4369 // It can be an undetectable object. 4290 // It can be an undetectable object.
4370 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset)); 4291 __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset));
4371 __ and_(edx, 1 << Map::kIsUndetectable); 4292 __ and_(edx, 1 << Map::kIsUndetectable);
4372 __ cmp(edx, 1 << Map::kIsUndetectable); 4293 __ cmp(edx, 1 << Map::kIsUndetectable);
4373 false_target()->Branch(equal); 4294 false_target()->Branch(equal);
4374 4295
4375 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 4296 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
4376 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); 4297 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
4377 false_target()->Branch(less); 4298 false_target()->Branch(less);
4378 __ cmp(ecx, LAST_JS_OBJECT_TYPE); 4299 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
4379 cc_reg_ = less_equal; 4300 true_target()->Branch(less_equal);
4301 false_target()->Jump();
4380 4302
4381 } else { 4303 } else {
4382 // Uncommon case: typeof testing against a string literal that is 4304 // Uncommon case: typeof testing against a string literal that is
4383 // never returned from the typeof operator. 4305 // never returned from the typeof operator.
4384 false_target()->Jump(); 4306 false_target()->Jump();
4385 // TODO(kmilliken) : Can this cause a problem because it is an expression
4386 // that exits without a virtual frame in place?
4387 } 4307 }
4388 return; 4308 return;
4389 } 4309 }
4390 4310
4391 Condition cc = no_condition; 4311 Condition cc = no_condition;
4392 bool strict = false; 4312 bool strict = false;
4393 switch (op) { 4313 switch (op) {
4394 case Token::EQ_STRICT: 4314 case Token::EQ_STRICT:
4395 strict = true; 4315 strict = true;
4396 // Fall through 4316 // Fall through
(...skipping 18 matching lines...) Expand all
4415 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2); 4335 frame_->InvokeBuiltin(Builtins::IN, CALL_FUNCTION, 2);
4416 frame_->Push(eax); // push the result 4336 frame_->Push(eax); // push the result
4417 return; 4337 return;
4418 } 4338 }
4419 case Token::INSTANCEOF: { 4339 case Token::INSTANCEOF: {
4420 Load(left); 4340 Load(left);
4421 Load(right); 4341 Load(right);
4422 InstanceofStub stub; 4342 InstanceofStub stub;
4423 frame_->CallStub(&stub, 2); 4343 frame_->CallStub(&stub, 2);
4424 __ test(eax, Operand(eax)); 4344 __ test(eax, Operand(eax));
4425 cc_reg_ = zero; 4345 true_target()->Branch(zero);
4346 false_target()->Jump();
4426 return; 4347 return;
4427 } 4348 }
4428 default: 4349 default:
4429 UNREACHABLE(); 4350 UNREACHABLE();
4430 } 4351 }
4431 4352
4432 // Optimize for the case where (at least) one of the expressions 4353 // Optimize for the case where (at least) one of the expressions
4433 // is a literal small integer. 4354 // is a literal small integer.
4434 if (IsInlineSmi(left->AsLiteral())) { 4355 if (IsInlineSmi(left->AsLiteral())) {
4435 Load(right); 4356 Load(right);
4436 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict); 4357 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict);
4437 return; 4358 } else if (IsInlineSmi(right->AsLiteral())) {
4438 }
4439 if (IsInlineSmi(right->AsLiteral())) {
4440 Load(left); 4359 Load(left);
4441 SmiComparison(cc, right->AsLiteral()->handle(), strict); 4360 SmiComparison(cc, right->AsLiteral()->handle(), strict);
4442 return; 4361 } else {
4362 Load(left);
4363 Load(right);
4364 Comparison(cc, strict, true_target(), false_target());
4443 } 4365 }
4444
4445 Load(left);
4446 Load(right);
4447 Comparison(cc, strict);
4448 } 4366 }
4449 4367
4450 4368
4451 #ifdef DEBUG 4369 #ifdef DEBUG
4452 bool CodeGenerator::HasValidEntryRegisters() { 4370 bool CodeGenerator::HasValidEntryRegisters() {
4453 return (allocator()->count(eax) == frame()->register_count(eax)) 4371 return (allocator()->count(eax) == frame()->register_count(eax))
4454 && (allocator()->count(ebx) == frame()->register_count(ebx)) 4372 && (allocator()->count(ebx) == frame()->register_count(ebx))
4455 && (allocator()->count(ecx) == frame()->register_count(ecx)) 4373 && (allocator()->count(ecx) == frame()->register_count(ecx))
4456 && (allocator()->count(edx) == frame()->register_count(edx)) 4374 && (allocator()->count(edx) == frame()->register_count(edx))
4457 && (allocator()->count(edi) == frame()->register_count(edi)); 4375 && (allocator()->count(edi) == frame()->register_count(edi));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
4527 Literal* raw_name = property->key()->AsLiteral(); 4445 Literal* raw_name = property->key()->AsLiteral();
4528 ASSERT(raw_name != NULL); 4446 ASSERT(raw_name != NULL);
4529 return Handle<String>(String::cast(*raw_name->handle())); 4447 return Handle<String>(String::cast(*raw_name->handle()));
4530 } 4448 }
4531 } 4449 }
4532 4450
4533 4451
4534 void Reference::GetValue(TypeofState typeof_state) { 4452 void Reference::GetValue(TypeofState typeof_state) {
4535 ASSERT(!cgen_->in_spilled_code()); 4453 ASSERT(!cgen_->in_spilled_code());
4536 ASSERT(!is_illegal()); 4454 ASSERT(!is_illegal());
4537 ASSERT(!cgen_->has_cc());
4538 MacroAssembler* masm = cgen_->masm(); 4455 MacroAssembler* masm = cgen_->masm();
4539 switch (type_) { 4456 switch (type_) {
4540 case SLOT: { 4457 case SLOT: {
4541 Comment cmnt(masm, "[ Load from Slot"); 4458 Comment cmnt(masm, "[ Load from Slot");
4542 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4459 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4543 ASSERT(slot != NULL); 4460 ASSERT(slot != NULL);
4544 cgen_->LoadFromSlot(slot, typeof_state); 4461 cgen_->LoadFromSlot(slot, typeof_state);
4545 break; 4462 break;
4546 } 4463 }
4547 4464
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
4680 UNREACHABLE(); 4597 UNREACHABLE();
4681 } 4598 }
4682 } 4599 }
4683 4600
4684 4601
4685 void Reference::TakeValue(TypeofState typeof_state) { 4602 void Reference::TakeValue(TypeofState typeof_state) {
4686 // For non-constant frame-allocated slots, we invalidate the value in the 4603 // For non-constant frame-allocated slots, we invalidate the value in the
4687 // slot. For all others, we fall back on GetValue. 4604 // slot. For all others, we fall back on GetValue.
4688 ASSERT(!cgen_->in_spilled_code()); 4605 ASSERT(!cgen_->in_spilled_code());
4689 ASSERT(!is_illegal()); 4606 ASSERT(!is_illegal());
4690 ASSERT(!cgen_->has_cc());
4691 if (type_ != SLOT) { 4607 if (type_ != SLOT) {
4692 GetValue(typeof_state); 4608 GetValue(typeof_state);
4693 return; 4609 return;
4694 } 4610 }
4695 4611
4696 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4612 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4697 ASSERT(slot != NULL); 4613 ASSERT(slot != NULL);
4698 if (slot->type() == Slot::LOOKUP || 4614 if (slot->type() == Slot::LOOKUP ||
4699 slot->type() == Slot::CONTEXT || 4615 slot->type() == Slot::CONTEXT ||
4700 slot->var()->mode() == Variable::CONST) { 4616 slot->var()->mode() == Variable::CONST) {
4701 GetValue(typeof_state); 4617 GetValue(typeof_state);
4702 return; 4618 return;
4703 } 4619 }
4704 4620
4705 // Only non-constant, frame-allocated parameters and locals can reach 4621 // Only non-constant, frame-allocated parameters and locals can reach
4706 // here. 4622 // here.
4707 if (slot->type() == Slot::PARAMETER) { 4623 if (slot->type() == Slot::PARAMETER) {
4708 cgen_->frame()->TakeParameterAt(slot->index()); 4624 cgen_->frame()->TakeParameterAt(slot->index());
4709 } else { 4625 } else {
4710 ASSERT(slot->type() == Slot::LOCAL); 4626 ASSERT(slot->type() == Slot::LOCAL);
4711 cgen_->frame()->TakeLocalAt(slot->index()); 4627 cgen_->frame()->TakeLocalAt(slot->index());
4712 } 4628 }
4713 } 4629 }
4714 4630
4715 4631
4716 void Reference::SetValue(InitState init_state) { 4632 void Reference::SetValue(InitState init_state) {
4717 ASSERT(!is_illegal()); 4633 ASSERT(!is_illegal());
4718 ASSERT(!cgen_->has_cc());
4719 MacroAssembler* masm = cgen_->masm(); 4634 MacroAssembler* masm = cgen_->masm();
4720 VirtualFrame* frame = cgen_->frame(); 4635 VirtualFrame* frame = cgen_->frame();
4721 switch (type_) { 4636 switch (type_) {
4722 case SLOT: { 4637 case SLOT: {
4723 Comment cmnt(masm, "[ Store to Slot"); 4638 Comment cmnt(masm, "[ Store to Slot");
4724 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 4639 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
4725 ASSERT(slot != NULL); 4640 ASSERT(slot != NULL);
4726 cgen_->StoreToSlot(slot, init_state); 4641 cgen_->StoreToSlot(slot, init_state);
4727 break; 4642 break;
4728 } 4643 }
(...skipping 1514 matching lines...) Expand 10 before | Expand all | Expand 10 after
6243 6158
6244 // Slow-case: Go through the JavaScript implementation. 6159 // Slow-case: Go through the JavaScript implementation.
6245 __ bind(&slow); 6160 __ bind(&slow);
6246 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 6161 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
6247 } 6162 }
6248 6163
6249 6164
6250 #undef __ 6165 #undef __
6251 6166
6252 } } // namespace v8::internal 6167 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698