OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 5147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5158 frame_->EmitPush(r0); | 5158 frame_->EmitPush(r0); |
5159 } | 5159 } |
5160 ASSERT_EQ(original_height + 1, frame_->height()); | 5160 ASSERT_EQ(original_height + 1, frame_->height()); |
5161 } | 5161 } |
5162 | 5162 |
5163 | 5163 |
5164 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 5164 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
5165 #ifdef DEBUG | 5165 #ifdef DEBUG |
5166 int original_height = frame_->height(); | 5166 int original_height = frame_->height(); |
5167 #endif | 5167 #endif |
5168 VirtualFrame::SpilledScope spilled_scope(frame_); | |
5169 Comment cmnt(masm_, "[ UnaryOperation"); | 5168 Comment cmnt(masm_, "[ UnaryOperation"); |
5170 | 5169 |
5171 Token::Value op = node->op(); | 5170 Token::Value op = node->op(); |
5172 | 5171 |
5173 if (op == Token::NOT) { | 5172 if (op == Token::NOT) { |
5174 LoadCondition(node->expression(), false_target(), true_target(), true); | 5173 LoadCondition(node->expression(), false_target(), true_target(), true); |
5175 // LoadCondition may (and usually does) leave a test and branch to | 5174 // LoadCondition may (and usually does) leave a test and branch to |
5176 // be emitted by the caller. In that case, negate the condition. | 5175 // be emitted by the caller. In that case, negate the condition. |
5177 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); | 5176 if (has_cc()) cc_reg_ = NegateCondition(cc_reg_); |
5178 | 5177 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5230 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5229 node->expression()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5231 Load(node->expression()); | 5230 Load(node->expression()); |
5232 switch (op) { | 5231 switch (op) { |
5233 case Token::NOT: | 5232 case Token::NOT: |
5234 case Token::DELETE: | 5233 case Token::DELETE: |
5235 case Token::TYPEOF: | 5234 case Token::TYPEOF: |
5236 UNREACHABLE(); // handled above | 5235 UNREACHABLE(); // handled above |
5237 break; | 5236 break; |
5238 | 5237 |
5239 case Token::SUB: { | 5238 case Token::SUB: { |
5240 VirtualFrame::SpilledScope spilled(frame_); | 5239 frame_->PopToR0(); |
5241 frame_->EmitPop(r0); | |
5242 GenericUnaryOpStub stub(Token::SUB, overwrite); | 5240 GenericUnaryOpStub stub(Token::SUB, overwrite); |
5243 frame_->CallStub(&stub, 0); | 5241 frame_->CallStub(&stub, 0); |
5244 frame_->EmitPush(r0); // r0 has result | 5242 frame_->EmitPush(r0); // r0 has result |
5245 break; | 5243 break; |
5246 } | 5244 } |
5247 | 5245 |
5248 case Token::BIT_NOT: { | 5246 case Token::BIT_NOT: { |
5249 // smi check | 5247 Register tos = frame_->PopToRegister(); |
5250 VirtualFrame::SpilledScope spilled(frame_); | 5248 JumpTarget not_smi_label; |
5251 frame_->EmitPop(r0); | |
5252 JumpTarget smi_label; | |
5253 JumpTarget continue_label; | 5249 JumpTarget continue_label; |
5254 __ tst(r0, Operand(kSmiTagMask)); | 5250 // Smi check. |
5255 smi_label.Branch(eq); | 5251 __ tst(tos, Operand(kSmiTagMask)); |
| 5252 not_smi_label.Branch(ne); |
5256 | 5253 |
| 5254 __ mvn(tos, Operand(tos)); |
| 5255 __ bic(tos, tos, Operand(kSmiTagMask)); // Bit-clear inverted smi-tag. |
| 5256 frame_->EmitPush(tos); |
| 5257 // The fast case is the first to jump to the continue label, so it gets |
| 5258 // to decide the virtual frame layout. |
| 5259 continue_label.Jump(); |
| 5260 |
| 5261 not_smi_label.Bind(); |
| 5262 frame_->SpillAll(); |
| 5263 __ Move(r0, tos); |
5257 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); | 5264 GenericUnaryOpStub stub(Token::BIT_NOT, overwrite); |
5258 frame_->CallStub(&stub, 0); | 5265 frame_->CallStub(&stub, 0); |
5259 continue_label.Jump(); | 5266 frame_->EmitPush(r0); |
5260 | 5267 |
5261 smi_label.Bind(); | |
5262 __ mvn(r0, Operand(r0)); | |
5263 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag | |
5264 continue_label.Bind(); | 5268 continue_label.Bind(); |
5265 frame_->EmitPush(r0); // r0 has result | |
5266 break; | 5269 break; |
5267 } | 5270 } |
5268 | 5271 |
5269 case Token::VOID: | 5272 case Token::VOID: |
5270 frame_->Drop(); | 5273 frame_->Drop(); |
5271 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); | 5274 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
5272 break; | 5275 break; |
5273 | 5276 |
5274 case Token::ADD: { | 5277 case Token::ADD: { |
5275 VirtualFrame::SpilledScope spilled(frame_); | 5278 Register tos = frame_->Peek(); |
5276 frame_->EmitPop(r0); | |
5277 // Smi check. | 5279 // Smi check. |
5278 JumpTarget continue_label; | 5280 JumpTarget continue_label; |
5279 __ tst(r0, Operand(kSmiTagMask)); | 5281 __ tst(tos, Operand(kSmiTagMask)); |
5280 continue_label.Branch(eq); | 5282 continue_label.Branch(eq); |
| 5283 |
| 5284 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); |
5281 frame_->EmitPush(r0); | 5285 frame_->EmitPush(r0); |
5282 frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1); | 5286 |
5283 continue_label.Bind(); | 5287 continue_label.Bind(); |
5284 frame_->EmitPush(r0); // r0 has result | |
5285 break; | 5288 break; |
5286 } | 5289 } |
5287 default: | 5290 default: |
5288 UNREACHABLE(); | 5291 UNREACHABLE(); |
5289 } | 5292 } |
5290 } | 5293 } |
5291 ASSERT(!has_valid_frame() || | 5294 ASSERT(!has_valid_frame() || |
5292 (has_cc() && frame_->height() == original_height) || | 5295 (has_cc() && frame_->height() == original_height) || |
5293 (!has_cc() && frame_->height() == original_height + 1)); | 5296 (!has_cc() && frame_->height() == original_height + 1)); |
5294 } | 5297 } |
5295 | 5298 |
5296 | 5299 |
5297 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 5300 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
5298 #ifdef DEBUG | 5301 #ifdef DEBUG |
5299 int original_height = frame_->height(); | 5302 int original_height = frame_->height(); |
5300 #endif | 5303 #endif |
5301 Comment cmnt(masm_, "[ CountOperation"); | 5304 Comment cmnt(masm_, "[ CountOperation"); |
| 5305 VirtualFrame::RegisterAllocationScope scope(this); |
5302 | 5306 |
5303 bool is_postfix = node->is_postfix(); | 5307 bool is_postfix = node->is_postfix(); |
5304 bool is_increment = node->op() == Token::INC; | 5308 bool is_increment = node->op() == Token::INC; |
5305 | 5309 |
5306 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); | 5310 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); |
5307 bool is_const = (var != NULL && var->mode() == Variable::CONST); | 5311 bool is_const = (var != NULL && var->mode() == Variable::CONST); |
5308 bool is_slot = (var != NULL && var->mode() == Variable::VAR); | 5312 bool is_slot = (var != NULL && var->mode() == Variable::VAR); |
5309 | 5313 |
5310 if (!is_const && is_slot && type_info(var->slot()).IsSmi()) { | 5314 if (!is_const && is_slot && type_info(var->slot()).IsSmi()) { |
5311 // The type info declares that this variable is always a Smi. That | 5315 // The type info declares that this variable is always a Smi. That |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5435 // operators must yield the result of one of the two expressions | 5439 // operators must yield the result of one of the two expressions |
5436 // before any ToBoolean() conversions. This means that the value | 5440 // before any ToBoolean() conversions. This means that the value |
5437 // produced by a && or || operator is not necessarily a boolean. | 5441 // produced by a && or || operator is not necessarily a boolean. |
5438 | 5442 |
5439 // NOTE: If the left hand side produces a materialized value (not in | 5443 // NOTE: If the left hand side produces a materialized value (not in |
5440 // the CC register), we force the right hand side to do the | 5444 // the CC register), we force the right hand side to do the |
5441 // same. This is necessary because we may have to branch to the exit | 5445 // same. This is necessary because we may have to branch to the exit |
5442 // after evaluating the left hand side (due to the shortcut | 5446 // after evaluating the left hand side (due to the shortcut |
5443 // semantics), but the compiler must (statically) know if the result | 5447 // semantics), but the compiler must (statically) know if the result |
5444 // of compiling the binary operation is materialized or not. | 5448 // of compiling the binary operation is materialized or not. |
5445 VirtualFrame::SpilledScope spilled_scope(frame_); | |
5446 if (node->op() == Token::AND) { | 5449 if (node->op() == Token::AND) { |
5447 JumpTarget is_true; | 5450 JumpTarget is_true; |
5448 LoadCondition(node->left(), &is_true, false_target(), false); | 5451 LoadCondition(node->left(), &is_true, false_target(), false); |
5449 if (has_valid_frame() && !has_cc()) { | 5452 if (has_valid_frame() && !has_cc()) { |
5450 // The left-hand side result is on top of the virtual frame. | 5453 // The left-hand side result is on top of the virtual frame. |
5451 JumpTarget pop_and_continue; | 5454 JumpTarget pop_and_continue; |
5452 JumpTarget exit; | 5455 JumpTarget exit; |
5453 | 5456 |
5454 frame_->Dup(); | 5457 frame_->Dup(); |
5455 // Avoid popping the result if it converts to 'false' using the | 5458 // Avoid popping the result if it converts to 'false' using the |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5620 // equality. | 5623 // equality. |
5621 if (op == Token::EQ || op == Token::EQ_STRICT) { | 5624 if (op == Token::EQ || op == Token::EQ_STRICT) { |
5622 bool left_is_null = | 5625 bool left_is_null = |
5623 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); | 5626 left->AsLiteral() != NULL && left->AsLiteral()->IsNull(); |
5624 bool right_is_null = | 5627 bool right_is_null = |
5625 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); | 5628 right->AsLiteral() != NULL && right->AsLiteral()->IsNull(); |
5626 // The 'null' value can only be equal to 'null' or 'undefined'. | 5629 // The 'null' value can only be equal to 'null' or 'undefined'. |
5627 if (left_is_null || right_is_null) { | 5630 if (left_is_null || right_is_null) { |
5628 Load(left_is_null ? right : left); | 5631 Load(left_is_null ? right : left); |
5629 Register tos = frame_->PopToRegister(); | 5632 Register tos = frame_->PopToRegister(); |
5630 // JumpTargets can't cope with register allocation yet. | |
5631 frame_->SpillAll(); | |
5632 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 5633 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
5633 __ cmp(tos, ip); | 5634 __ cmp(tos, ip); |
5634 | 5635 |
5635 // The 'null' value is only equal to 'undefined' if using non-strict | 5636 // The 'null' value is only equal to 'undefined' if using non-strict |
5636 // comparisons. | 5637 // comparisons. |
5637 if (op != Token::EQ_STRICT) { | 5638 if (op != Token::EQ_STRICT) { |
5638 true_target()->Branch(eq); | 5639 true_target()->Branch(eq); |
5639 | 5640 |
5640 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5641 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
5641 __ cmp(tos, Operand(ip)); | 5642 __ cmp(tos, Operand(ip)); |
(...skipping 22 matching lines...) Expand all Loading... |
5664 if ((op == Token::EQ || op == Token::EQ_STRICT) && | 5665 if ((op == Token::EQ || op == Token::EQ_STRICT) && |
5665 (operation != NULL && operation->op() == Token::TYPEOF) && | 5666 (operation != NULL && operation->op() == Token::TYPEOF) && |
5666 (right->AsLiteral() != NULL && | 5667 (right->AsLiteral() != NULL && |
5667 right->AsLiteral()->handle()->IsString())) { | 5668 right->AsLiteral()->handle()->IsString())) { |
5668 Handle<String> check(String::cast(*right->AsLiteral()->handle())); | 5669 Handle<String> check(String::cast(*right->AsLiteral()->handle())); |
5669 | 5670 |
5670 // Load the operand, move it to a register. | 5671 // Load the operand, move it to a register. |
5671 LoadTypeofExpression(operation->expression()); | 5672 LoadTypeofExpression(operation->expression()); |
5672 Register tos = frame_->PopToRegister(); | 5673 Register tos = frame_->PopToRegister(); |
5673 | 5674 |
5674 // JumpTargets can't cope with register allocation yet. | |
5675 frame_->SpillAll(); | |
5676 | |
5677 Register scratch = VirtualFrame::scratch0(); | 5675 Register scratch = VirtualFrame::scratch0(); |
5678 | 5676 |
5679 if (check->Equals(Heap::number_symbol())) { | 5677 if (check->Equals(Heap::number_symbol())) { |
5680 __ tst(tos, Operand(kSmiTagMask)); | 5678 __ tst(tos, Operand(kSmiTagMask)); |
5681 true_target()->Branch(eq); | 5679 true_target()->Branch(eq); |
5682 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); | 5680 __ ldr(tos, FieldMemOperand(tos, HeapObject::kMapOffset)); |
5683 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 5681 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
5684 __ cmp(tos, ip); | 5682 __ cmp(tos, ip); |
5685 cc_reg_ = eq; | 5683 cc_reg_ = eq; |
5686 | 5684 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5787 | 5785 |
5788 case Token::GTE: | 5786 case Token::GTE: |
5789 Comparison(ge, left, right); | 5787 Comparison(ge, left, right); |
5790 break; | 5788 break; |
5791 | 5789 |
5792 case Token::EQ_STRICT: | 5790 case Token::EQ_STRICT: |
5793 Comparison(eq, left, right, true); | 5791 Comparison(eq, left, right, true); |
5794 break; | 5792 break; |
5795 | 5793 |
5796 case Token::IN: { | 5794 case Token::IN: { |
5797 VirtualFrame::SpilledScope scope(frame_); | |
5798 Load(left); | 5795 Load(left); |
5799 Load(right); | 5796 Load(right); |
5800 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); | 5797 frame_->InvokeBuiltin(Builtins::IN, CALL_JS, 2); |
5801 frame_->EmitPush(r0); | 5798 frame_->EmitPush(r0); |
5802 break; | 5799 break; |
5803 } | 5800 } |
5804 | 5801 |
5805 case Token::INSTANCEOF: { | 5802 case Token::INSTANCEOF: { |
5806 VirtualFrame::SpilledScope scope(frame_); | |
5807 Load(left); | 5803 Load(left); |
5808 Load(right); | 5804 Load(right); |
5809 InstanceofStub stub; | 5805 InstanceofStub stub; |
5810 frame_->CallStub(&stub, 2); | 5806 frame_->CallStub(&stub, 2); |
5811 // At this point if instanceof succeeded then r0 == 0. | 5807 // At this point if instanceof succeeded then r0 == 0. |
5812 __ tst(r0, Operand(r0)); | 5808 __ tst(r0, Operand(r0)); |
5813 cc_reg_ = eq; | 5809 cc_reg_ = eq; |
5814 break; | 5810 break; |
5815 } | 5811 } |
5816 | 5812 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5894 } | 5890 } |
5895 | 5891 |
5896 virtual void Generate(); | 5892 virtual void Generate(); |
5897 | 5893 |
5898 private: | 5894 private: |
5899 Register key_; | 5895 Register key_; |
5900 Register receiver_; | 5896 Register receiver_; |
5901 }; | 5897 }; |
5902 | 5898 |
5903 | 5899 |
| 5900 // Takes key and register in r0 and r1 or vice versa. Returns result |
| 5901 // in r0. |
5904 void DeferredReferenceGetKeyedValue::Generate() { | 5902 void DeferredReferenceGetKeyedValue::Generate() { |
5905 ASSERT((key_.is(r0) && receiver_.is(r1)) || | 5903 ASSERT((key_.is(r0) && receiver_.is(r1)) || |
5906 (key_.is(r1) && receiver_.is(r0))); | 5904 (key_.is(r1) && receiver_.is(r0))); |
5907 | 5905 |
| 5906 VirtualFrame copied_frame(*frame_state()->frame()); |
| 5907 copied_frame.SpillAll(); |
| 5908 |
5908 Register scratch1 = VirtualFrame::scratch0(); | 5909 Register scratch1 = VirtualFrame::scratch0(); |
5909 Register scratch2 = VirtualFrame::scratch1(); | 5910 Register scratch2 = VirtualFrame::scratch1(); |
5910 __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2); | 5911 __ DecrementCounter(&Counters::keyed_load_inline, 1, scratch1, scratch2); |
5911 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2); | 5912 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1, scratch1, scratch2); |
5912 | 5913 |
5913 // Ensure key in r0 and receiver in r1 to match keyed load ic calling | 5914 // Ensure key in r0 and receiver in r1 to match keyed load ic calling |
5914 // convention. | 5915 // convention. |
5915 if (key_.is(r1)) { | 5916 if (key_.is(r1)) { |
5916 __ Swap(r0, r1, ip); | 5917 __ Swap(r0, r1, ip); |
5917 } | 5918 } |
5918 | 5919 |
5919 // The rest of the instructions in the deferred code must be together. | 5920 // The rest of the instructions in the deferred code must be together. |
5920 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 5921 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
5921 // Call keyed load IC. It has the arguments key and receiver in r0 and r1. | 5922 // Call keyed load IC. It has the arguments key and receiver in r0 and r1. |
5922 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 5923 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
5923 __ Call(ic, RelocInfo::CODE_TARGET); | 5924 __ Call(ic, RelocInfo::CODE_TARGET); |
5924 // The call must be followed by a nop instruction to indicate that the | 5925 // The call must be followed by a nop instruction to indicate that the |
5925 // keyed load has been inlined. | 5926 // keyed load has been inlined. |
5926 __ nop(PROPERTY_ACCESS_INLINED); | 5927 __ nop(PROPERTY_ACCESS_INLINED); |
5927 | 5928 |
| 5929 // Now go back to the frame that we entered with. This will not overwrite |
| 5930 // the receiver or key registers since they were not in use when we came |
| 5931 // in. The instructions emitted by this merge are skipped over by the |
| 5932 // inline load patching mechanism when looking for the branch instruction |
| 5933 // that tells it where the code to patch is. |
| 5934 copied_frame.MergeTo(frame_state()->frame()); |
| 5935 |
5928 // Block the constant pool for one more instruction after leaving this | 5936 // Block the constant pool for one more instruction after leaving this |
5929 // constant pool block scope to include the branch instruction ending the | 5937 // constant pool block scope to include the branch instruction ending the |
5930 // deferred code. | 5938 // deferred code. |
5931 __ BlockConstPoolFor(1); | 5939 __ BlockConstPoolFor(1); |
5932 } | 5940 } |
5933 } | 5941 } |
5934 | 5942 |
5935 | 5943 |
5936 class DeferredReferenceSetKeyedValue: public DeferredCode { | 5944 class DeferredReferenceSetKeyedValue: public DeferredCode { |
5937 public: | 5945 public: |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6071 | 6079 |
6072 // Counter will be decremented in the deferred code. Placed here to avoid | 6080 // Counter will be decremented in the deferred code. Placed here to avoid |
6073 // having it in the instruction stream below where patching will occur. | 6081 // having it in the instruction stream below where patching will occur. |
6074 __ IncrementCounter(&Counters::keyed_load_inline, 1, | 6082 __ IncrementCounter(&Counters::keyed_load_inline, 1, |
6075 frame_->scratch0(), frame_->scratch1()); | 6083 frame_->scratch0(), frame_->scratch1()); |
6076 | 6084 |
6077 // Load the key and receiver from the stack. | 6085 // Load the key and receiver from the stack. |
6078 bool key_is_known_smi = frame_->KnownSmiAt(0); | 6086 bool key_is_known_smi = frame_->KnownSmiAt(0); |
6079 Register key = frame_->PopToRegister(); | 6087 Register key = frame_->PopToRegister(); |
6080 Register receiver = frame_->PopToRegister(key); | 6088 Register receiver = frame_->PopToRegister(key); |
6081 VirtualFrame::SpilledScope spilled(frame_); | |
6082 | 6089 |
6083 // The deferred code expects key and receiver in registers. | 6090 // The deferred code expects key and receiver in registers. |
6084 DeferredReferenceGetKeyedValue* deferred = | 6091 DeferredReferenceGetKeyedValue* deferred = |
6085 new DeferredReferenceGetKeyedValue(key, receiver); | 6092 new DeferredReferenceGetKeyedValue(key, receiver); |
6086 | 6093 |
6087 // Check that the receiver is a heap object. | 6094 // Check that the receiver is a heap object. |
6088 __ tst(receiver, Operand(kSmiTagMask)); | 6095 __ tst(receiver, Operand(kSmiTagMask)); |
6089 deferred->Branch(eq); | 6096 deferred->Branch(eq); |
6090 | 6097 |
6091 // The following instructions are the part of the inlined load keyed | 6098 // The following instructions are the part of the inlined load keyed |
(...skipping 4604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10696 __ bind(&string_add_runtime); | 10703 __ bind(&string_add_runtime); |
10697 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10704 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10698 } | 10705 } |
10699 | 10706 |
10700 | 10707 |
10701 #undef __ | 10708 #undef __ |
10702 | 10709 |
10703 } } // namespace v8::internal | 10710 } } // namespace v8::internal |
10704 | 10711 |
10705 #endif // V8_TARGET_ARCH_ARM | 10712 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |