OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1479 if (node->starts_initialization_block()) { | 1479 if (node->starts_initialization_block()) { |
1480 ASSERT(target.type() == Reference::NAMED || | 1480 ASSERT(target.type() == Reference::NAMED || |
1481 target.type() == Reference::KEYED); | 1481 target.type() == Reference::KEYED); |
1482 // Change to slow case in the beginning of an initialization | 1482 // Change to slow case in the beginning of an initialization |
1483 // block to avoid the quadratic behavior of repeatedly adding | 1483 // block to avoid the quadratic behavior of repeatedly adding |
1484 // fast properties. | 1484 // fast properties. |
1485 | 1485 |
1486 // The receiver is the argument to the runtime call. It is the | 1486 // The receiver is the argument to the runtime call. It is the |
1487 // first value pushed when the reference was loaded to the | 1487 // first value pushed when the reference was loaded to the |
1488 // frame. | 1488 // frame. |
1489 frame_->PushElementAt(target.size() - 1); | 1489 // TODO(X64): Enable this and the switch back to fast, once they work. |
| 1490 // frame_->PushElementAt(target.size() - 1); |
1490 // Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); | 1491 // Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); |
1491 } | 1492 } |
1492 if (node->op() == Token::ASSIGN || | 1493 if (node->op() == Token::ASSIGN || |
1493 node->op() == Token::INIT_VAR || | 1494 node->op() == Token::INIT_VAR || |
1494 node->op() == Token::INIT_CONST) { | 1495 node->op() == Token::INIT_CONST) { |
1495 Load(node->value()); | 1496 Load(node->value()); |
1496 | 1497 |
1497 } else { | 1498 } else { |
1498 Literal* literal = node->value()->AsLiteral(); | 1499 Literal* literal = node->value()->AsLiteral(); |
1499 bool overwrite_value = | 1500 bool overwrite_value = |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1531 } else { | 1532 } else { |
1532 target.SetValue(NOT_CONST_INIT); | 1533 target.SetValue(NOT_CONST_INIT); |
1533 } | 1534 } |
1534 if (node->ends_initialization_block()) { | 1535 if (node->ends_initialization_block()) { |
1535 ASSERT(target.type() == Reference::NAMED || | 1536 ASSERT(target.type() == Reference::NAMED || |
1536 target.type() == Reference::KEYED); | 1537 target.type() == Reference::KEYED); |
1537 // End of initialization block. Revert to fast case. The | 1538 // End of initialization block. Revert to fast case. The |
1538 // argument to the runtime call is the receiver, which is the | 1539 // argument to the runtime call is the receiver, which is the |
1539 // first value pushed as part of the reference, which is below | 1540 // first value pushed as part of the reference, which is below |
1540 // the lhs value. | 1541 // the lhs value. |
1541 frame_->PushElementAt(target.size()); | 1542 // TODO(X64): Enable this once ToFastProperties works. |
| 1543 // frame_->PushElementAt(target.size()); |
1542 // Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); | 1544 // Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1); |
1543 } | 1545 } |
1544 } | 1546 } |
1545 } | 1547 } |
1546 } | 1548 } |
1547 | 1549 |
1548 | 1550 |
1549 void CodeGenerator::VisitThrow(Throw* node) { | 1551 void CodeGenerator::VisitThrow(Throw* node) { |
1550 Comment cmnt(masm_, "[ Throw"); | 1552 Comment cmnt(masm_, "[ Throw"); |
1551 CodeForStatementPosition(node); | 1553 CodeForStatementPosition(node); |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2298 Expression* right = node->right(); | 2300 Expression* right = node->right(); |
2299 Token::Value op = node->op(); | 2301 Token::Value op = node->op(); |
2300 // To make typeof testing for natives implemented in JavaScript really | 2302 // To make typeof testing for natives implemented in JavaScript really |
2301 // efficient, we generate special code for expressions of the form: | 2303 // efficient, we generate special code for expressions of the form: |
2302 // 'typeof <expression> == <string>'. | 2304 // 'typeof <expression> == <string>'. |
2303 UnaryOperation* operation = left->AsUnaryOperation(); | 2305 UnaryOperation* operation = left->AsUnaryOperation(); |
2304 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 2306 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
2305 (operation != NULL && operation->op() == Token::TYPEOF) && | 2307 (operation != NULL && operation->op() == Token::TYPEOF) && |
2306 (right->AsLiteral() != NULL && | 2308 (right->AsLiteral() != NULL && |
2307 right->AsLiteral()->handle()->IsString())) { | 2309 right->AsLiteral()->handle()->IsString())) { |
2308 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 2310 Handle<String> check(Handle<String>::cast(right->AsLiteral()->handle())); |
2309 | 2311 |
2310 // Load the operand and move it to a register. | 2312 // Load the operand and move it to a register. |
2311 LoadTypeofExpression(operation->expression()); | 2313 LoadTypeofExpression(operation->expression()); |
2312 Result answer = frame_->Pop(); | 2314 Result answer = frame_->Pop(); |
2313 answer.ToRegister(); | 2315 answer.ToRegister(); |
2314 | 2316 |
2315 if (check->Equals(Heap::number_symbol())) { | 2317 if (check->Equals(Heap::number_symbol())) { |
2316 __ testl(answer.reg(), Immediate(kSmiTagMask)); | 2318 __ testl(answer.reg(), Immediate(kSmiTagMask)); |
2317 destination()->true_target()->Branch(zero); | 2319 destination()->true_target()->Branch(zero); |
2318 frame_->Spill(answer.reg()); | 2320 frame_->Spill(answer.reg()); |
(...skipping 931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3250 JumpTarget is_smi; | 3252 JumpTarget is_smi; |
3251 Register left_reg = left_side.reg(); | 3253 Register left_reg = left_side.reg(); |
3252 Handle<Object> right_val = right_side.handle(); | 3254 Handle<Object> right_val = right_side.handle(); |
3253 __ testl(left_side.reg(), Immediate(kSmiTagMask)); | 3255 __ testl(left_side.reg(), Immediate(kSmiTagMask)); |
3254 is_smi.Branch(zero, taken); | 3256 is_smi.Branch(zero, taken); |
3255 | 3257 |
3256 // Setup and call the compare stub. | 3258 // Setup and call the compare stub. |
3257 CompareStub stub(cc, strict); | 3259 CompareStub stub(cc, strict); |
3258 Result result = frame_->CallStub(&stub, &left_side, &right_side); | 3260 Result result = frame_->CallStub(&stub, &left_side, &right_side); |
3259 result.ToRegister(); | 3261 result.ToRegister(); |
3260 __ cmpq(result.reg(), Immediate(0)); | 3262 __ testq(result.reg(), result.reg()); |
3261 result.Unuse(); | 3263 result.Unuse(); |
3262 dest->true_target()->Branch(cc); | 3264 dest->true_target()->Branch(cc); |
3263 dest->false_target()->Jump(); | 3265 dest->false_target()->Jump(); |
3264 | 3266 |
3265 is_smi.Bind(); | 3267 is_smi.Bind(); |
3266 left_side = Result(left_reg); | 3268 left_side = Result(left_reg); |
3267 right_side = Result(right_val); | 3269 right_side = Result(right_val); |
3268 // Test smi equality and comparison by signed int comparison. | 3270 // Test smi equality and comparison by signed int comparison. |
3269 if (IsUnsafeSmi(right_side.handle())) { | 3271 if (IsUnsafeSmi(right_side.handle())) { |
3270 right_side.ToRegister(); | 3272 right_side.ToRegister(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3316 bool known_non_smi = | 3318 bool known_non_smi = |
3317 (left_side.is_constant() && !left_side.handle()->IsSmi()) || | 3319 (left_side.is_constant() && !left_side.handle()->IsSmi()) || |
3318 (right_side.is_constant() && !right_side.handle()->IsSmi()); | 3320 (right_side.is_constant() && !right_side.handle()->IsSmi()); |
3319 left_side.ToRegister(); | 3321 left_side.ToRegister(); |
3320 right_side.ToRegister(); | 3322 right_side.ToRegister(); |
3321 | 3323 |
3322 if (known_non_smi) { | 3324 if (known_non_smi) { |
3323 // When non-smi, call out to the compare stub. | 3325 // When non-smi, call out to the compare stub. |
3324 CompareStub stub(cc, strict); | 3326 CompareStub stub(cc, strict); |
3325 Result answer = frame_->CallStub(&stub, &left_side, &right_side); | 3327 Result answer = frame_->CallStub(&stub, &left_side, &right_side); |
3326 if (cc == equal) { | 3328 __ testq(answer.reg(), answer.reg()); // Both zero and sign flag right. |
3327 __ testq(answer.reg(), answer.reg()); | |
3328 } else { | |
3329 __ cmpq(answer.reg(), Immediate(0)); | |
3330 } | |
3331 answer.Unuse(); | 3329 answer.Unuse(); |
3332 dest->Split(cc); | 3330 dest->Split(cc); |
3333 } else { | 3331 } else { |
3334 // Here we split control flow to the stub call and inlined cases | 3332 // Here we split control flow to the stub call and inlined cases |
3335 // before finally splitting it to the control destination. We use | 3333 // before finally splitting it to the control destination. We use |
3336 // a jump target and branching to duplicate the virtual frame at | 3334 // a jump target and branching to duplicate the virtual frame at |
3337 // the first split. We manually handle the off-frame references | 3335 // the first split. We manually handle the off-frame references |
3338 // by reconstituting them on the non-fall-through path. | 3336 // by reconstituting them on the non-fall-through path. |
3339 JumpTarget is_smi; | 3337 JumpTarget is_smi; |
3340 Register left_reg = left_side.reg(); | 3338 Register left_reg = left_side.reg(); |
(...skipping 2463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5804 break; | 5802 break; |
5805 default: | 5803 default: |
5806 UNREACHABLE(); | 5804 UNREACHABLE(); |
5807 } | 5805 } |
5808 } | 5806 } |
5809 | 5807 |
5810 | 5808 |
5811 #undef __ | 5809 #undef __ |
5812 | 5810 |
5813 } } // namespace v8::internal | 5811 } } // namespace v8::internal |
OLD | NEW |