| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; | 261 int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; |
| 262 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); | 262 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); |
| 263 __ RecordJSReturn(); | 263 __ RecordJSReturn(); |
| 264 masm_->mov(sp, fp); | 264 masm_->mov(sp, fp); |
| 265 masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); | 265 masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 266 masm_->add(sp, sp, Operand(sp_delta)); | 266 masm_->add(sp, sp, Operand(sp_delta)); |
| 267 masm_->Jump(lr); | 267 masm_->Jump(lr); |
| 268 } | 268 } |
| 269 | 269 |
| 270 #ifdef DEBUG | 270 #ifdef DEBUG |
| 271 // Check that the size of the code used for returning matches what is | 271 // Check that the size of the code used for returning is large enough |
| 272 // expected by the debugger. If the sp_delts above cannot be encoded in the | 272 // for the debugger's requirements. |
| 273 // add instruction the add will generate two instructions. | 273 ASSERT(Assembler::kJSReturnSequenceInstructions <= |
| 274 int return_sequence_length = | 274 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
| 275 masm_->InstructionsGeneratedSince(&check_exit_codesize); | |
| 276 CHECK(return_sequence_length == | |
| 277 Assembler::kJSReturnSequenceInstructions || | |
| 278 return_sequence_length == | |
| 279 Assembler::kJSReturnSequenceInstructions + 1); | |
| 280 #endif | 275 #endif |
| 281 } | 276 } |
| 282 } | 277 } |
| 283 | 278 |
| 284 | 279 |
| 285 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( | 280 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( |
| 286 Token::Value op, Expression* left, Expression* right) { | 281 Token::Value op, Expression* left, Expression* right) { |
| 287 ASSERT(ShouldInlineSmiCase(op)); | 282 ASSERT(ShouldInlineSmiCase(op)); |
| 288 return kNoConstants; | 283 return kNoConstants; |
| 289 } | 284 } |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 __ Push(cp, r2, r1, r0); | 669 __ Push(cp, r2, r1, r0); |
| 675 } | 670 } |
| 676 __ CallRuntime(Runtime::kDeclareContextSlot, 4); | 671 __ CallRuntime(Runtime::kDeclareContextSlot, 4); |
| 677 break; | 672 break; |
| 678 } | 673 } |
| 679 } | 674 } |
| 680 | 675 |
| 681 } else if (prop != NULL) { | 676 } else if (prop != NULL) { |
| 682 if (function != NULL || mode == Variable::CONST) { | 677 if (function != NULL || mode == Variable::CONST) { |
| 683 // We are declaring a function or constant that rewrites to a | 678 // We are declaring a function or constant that rewrites to a |
| 684 // property. Use (keyed) IC to set the initial value. | 679 // property. Use (keyed) IC to set the initial value. We |
| 685 VisitForStackValue(prop->obj()); | 680 // cannot visit the rewrite because it's shared and we risk |
| 681 // recording duplicate AST IDs for bailouts from optimized code. |
| 682 ASSERT(prop->obj()->AsVariableProxy() != NULL); |
| 683 { AccumulatorValueContext for_object(this); |
| 684 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); |
| 685 } |
| 686 if (function != NULL) { | 686 if (function != NULL) { |
| 687 VisitForStackValue(prop->key()); | 687 __ push(r0); |
| 688 VisitForAccumulatorValue(function); | 688 VisitForAccumulatorValue(function); |
| 689 __ pop(r1); // Key. | 689 __ pop(r2); |
| 690 } else { | 690 } else { |
| 691 VisitForAccumulatorValue(prop->key()); | 691 __ mov(r2, r0); |
| 692 __ mov(r1, result_register()); // Key. | 692 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 693 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex); | |
| 694 } | 693 } |
| 695 __ pop(r2); // Receiver. | 694 ASSERT(prop->key()->AsLiteral() != NULL && |
| 695 prop->key()->AsLiteral()->handle()->IsSmi()); |
| 696 __ mov(r1, Operand(prop->key()->AsLiteral()->handle())); |
| 696 | 697 |
| 697 Handle<Code> ic(isolate()->builtins()->builtin( | 698 Handle<Code> ic(isolate()->builtins()->builtin( |
| 698 Builtins::KeyedStoreIC_Initialize)); | 699 Builtins::KeyedStoreIC_Initialize)); |
| 699 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 700 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
| 700 // Value in r0 is ignored (declarations are statements). | 701 // Value in r0 is ignored (declarations are statements). |
| 701 } | 702 } |
| 702 } | 703 } |
| 703 } | 704 } |
| 704 | 705 |
| 705 | 706 |
| (...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1553 Expression* right, | 1554 Expression* right, |
| 1554 ConstantOperand constant) { | 1555 ConstantOperand constant) { |
| 1555 ASSERT(constant == kNoConstants); // Only handled case. | 1556 ASSERT(constant == kNoConstants); // Only handled case. |
| 1556 EmitBinaryOp(op, mode); | 1557 EmitBinaryOp(op, mode); |
| 1557 } | 1558 } |
| 1558 | 1559 |
| 1559 | 1560 |
| 1560 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1561 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
| 1561 OverwriteMode mode) { | 1562 OverwriteMode mode) { |
| 1562 __ pop(r1); | 1563 __ pop(r1); |
| 1563 if (op == Token::ADD || op == Token::SUB) { | 1564 if (op == Token::ADD || |
| 1565 op == Token::SUB || |
| 1566 op == Token::MUL || |
| 1567 op == Token::DIV || |
| 1568 op == Token::MOD || |
| 1569 op == Token::BIT_OR || |
| 1570 op == Token::BIT_AND || |
| 1571 op == Token::BIT_XOR) { |
| 1564 TypeRecordingBinaryOpStub stub(op, mode); | 1572 TypeRecordingBinaryOpStub stub(op, mode); |
| 1565 __ CallStub(&stub); | 1573 __ CallStub(&stub); |
| 1566 } else { | 1574 } else { |
| 1567 GenericBinaryOpStub stub(op, mode, r1, r0); | 1575 GenericBinaryOpStub stub(op, mode, r1, r0); |
| 1568 __ CallStub(&stub); | 1576 __ CallStub(&stub); |
| 1569 } | 1577 } |
| 1570 context()->Plug(r0); | 1578 context()->Plug(r0); |
| 1571 } | 1579 } |
| 1572 | 1580 |
| 1573 | 1581 |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1929 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 1937 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 1930 __ push(r1); | 1938 __ push(r1); |
| 1931 } else { | 1939 } else { |
| 1932 __ push(r2); | 1940 __ push(r2); |
| 1933 } | 1941 } |
| 1934 | 1942 |
| 1935 // Push the receiver of the enclosing function and do runtime call. | 1943 // Push the receiver of the enclosing function and do runtime call. |
| 1936 __ ldr(r1, | 1944 __ ldr(r1, |
| 1937 MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); | 1945 MemOperand(fp, (2 + scope()->num_parameters()) * kPointerSize)); |
| 1938 __ push(r1); | 1946 __ push(r1); |
| 1939 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); | 1947 // Push the strict mode flag. |
| 1948 __ mov(r1, Operand(Smi::FromInt(strict_mode_flag()))); |
| 1949 __ push(r1); |
| 1950 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); |
| 1940 | 1951 |
| 1941 // The runtime call returns a pair of values in r0 (function) and | 1952 // The runtime call returns a pair of values in r0 (function) and |
| 1942 // r1 (receiver). Touch up the stack with the right values. | 1953 // r1 (receiver). Touch up the stack with the right values. |
| 1943 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1954 __ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 1944 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); | 1955 __ str(r1, MemOperand(sp, arg_count * kPointerSize)); |
| 1945 } | 1956 } |
| 1946 | 1957 |
| 1947 // Record source position for debugger. | 1958 // Record source position for debugger. |
| 1948 SetSourcePosition(expr->position()); | 1959 SetSourcePosition(expr->position()); |
| 1949 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1960 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| (...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3070 context()->Plug(r0); | 3081 context()->Plug(r0); |
| 3071 break; | 3082 break; |
| 3072 } | 3083 } |
| 3073 | 3084 |
| 3074 case Token::ADD: { | 3085 case Token::ADD: { |
| 3075 Comment cmt(masm_, "[ UnaryOperation (ADD)"); | 3086 Comment cmt(masm_, "[ UnaryOperation (ADD)"); |
| 3076 VisitForAccumulatorValue(expr->expression()); | 3087 VisitForAccumulatorValue(expr->expression()); |
| 3077 Label no_conversion; | 3088 Label no_conversion; |
| 3078 __ tst(result_register(), Operand(kSmiTagMask)); | 3089 __ tst(result_register(), Operand(kSmiTagMask)); |
| 3079 __ b(eq, &no_conversion); | 3090 __ b(eq, &no_conversion); |
| 3080 __ push(r0); | 3091 ToNumberStub convert_stub; |
| 3081 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 3092 __ CallStub(&convert_stub); |
| 3082 __ bind(&no_conversion); | 3093 __ bind(&no_conversion); |
| 3083 context()->Plug(result_register()); | 3094 context()->Plug(result_register()); |
| 3084 break; | 3095 break; |
| 3085 } | 3096 } |
| 3086 | 3097 |
| 3087 case Token::SUB: { | 3098 case Token::SUB: { |
| 3088 Comment cmt(masm_, "[ UnaryOperation (SUB)"); | 3099 Comment cmt(masm_, "[ UnaryOperation (SUB)"); |
| 3089 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); | 3100 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
| 3090 UnaryOverwriteMode overwrite = | 3101 UnaryOverwriteMode overwrite = |
| 3091 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 3102 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3190 } | 3201 } |
| 3191 } | 3202 } |
| 3192 | 3203 |
| 3193 // We need a second deoptimization point after loading the value | 3204 // We need a second deoptimization point after loading the value |
| 3194 // in case evaluating the property load my have a side effect. | 3205 // in case evaluating the property load my have a side effect. |
| 3195 PrepareForBailout(expr->increment(), TOS_REG); | 3206 PrepareForBailout(expr->increment(), TOS_REG); |
| 3196 | 3207 |
| 3197 // Call ToNumber only if operand is not a smi. | 3208 // Call ToNumber only if operand is not a smi. |
| 3198 Label no_conversion; | 3209 Label no_conversion; |
| 3199 __ JumpIfSmi(r0, &no_conversion); | 3210 __ JumpIfSmi(r0, &no_conversion); |
| 3200 __ push(r0); | 3211 ToNumberStub convert_stub; |
| 3201 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 3212 __ CallStub(&convert_stub); |
| 3202 __ bind(&no_conversion); | 3213 __ bind(&no_conversion); |
| 3203 | 3214 |
| 3204 // Save result for postfix expressions. | 3215 // Save result for postfix expressions. |
| 3205 if (expr->is_postfix()) { | 3216 if (expr->is_postfix()) { |
| 3206 if (!context()->IsEffect()) { | 3217 if (!context()->IsEffect()) { |
| 3207 // Save the result on the stack. If we have a named or keyed property | 3218 // Save the result on the stack. If we have a named or keyed property |
| 3208 // we store the result under the receiver that is currently on top | 3219 // we store the result under the receiver that is currently on top |
| 3209 // of the stack. | 3220 // of the stack. |
| 3210 switch (assign_type) { | 3221 switch (assign_type) { |
| 3211 case VARIABLE: | 3222 case VARIABLE: |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3641 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3652 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 3642 __ add(pc, r1, Operand(masm_->CodeObject())); | 3653 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 3643 } | 3654 } |
| 3644 | 3655 |
| 3645 | 3656 |
| 3646 #undef __ | 3657 #undef __ |
| 3647 | 3658 |
| 3648 } } // namespace v8::internal | 3659 } } // namespace v8::internal |
| 3649 | 3660 |
| 3650 #endif // V8_TARGET_ARCH_ARM | 3661 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |