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 2708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2719 frame_->CallRuntime(Runtime::kNewClosure, 2); | 2719 frame_->CallRuntime(Runtime::kNewClosure, 2); |
2720 frame_->EmitPush(r0); | 2720 frame_->EmitPush(r0); |
2721 } | 2721 } |
2722 } | 2722 } |
2723 | 2723 |
2724 | 2724 |
2725 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 2725 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
2726 #ifdef DEBUG | 2726 #ifdef DEBUG |
2727 int original_height = frame_->height(); | 2727 int original_height = frame_->height(); |
2728 #endif | 2728 #endif |
2729 VirtualFrame::SpilledScope spilled_scope(frame_); | |
2730 Comment cmnt(masm_, "[ FunctionLiteral"); | 2729 Comment cmnt(masm_, "[ FunctionLiteral"); |
2731 | 2730 |
2732 // Build the function info and instantiate it. | 2731 // Build the function info and instantiate it. |
2733 Handle<SharedFunctionInfo> function_info = | 2732 Handle<SharedFunctionInfo> function_info = |
2734 Compiler::BuildFunctionInfo(node, script(), this); | 2733 Compiler::BuildFunctionInfo(node, script(), this); |
2735 // Check for stack-overflow exception. | 2734 // Check for stack-overflow exception. |
2736 if (HasStackOverflow()) { | 2735 if (HasStackOverflow()) { |
2737 ASSERT(frame_->height() == original_height); | 2736 ASSERT(frame_->height() == original_height); |
2738 return; | 2737 return; |
2739 } | 2738 } |
2740 InstantiateFunction(function_info); | 2739 InstantiateFunction(function_info); |
2741 ASSERT_EQ(original_height + 1, frame_->height()); | 2740 ASSERT_EQ(original_height + 1, frame_->height()); |
2742 } | 2741 } |
2743 | 2742 |
2744 | 2743 |
2745 void CodeGenerator::VisitSharedFunctionInfoLiteral( | 2744 void CodeGenerator::VisitSharedFunctionInfoLiteral( |
2746 SharedFunctionInfoLiteral* node) { | 2745 SharedFunctionInfoLiteral* node) { |
2747 #ifdef DEBUG | 2746 #ifdef DEBUG |
2748 int original_height = frame_->height(); | 2747 int original_height = frame_->height(); |
2749 #endif | 2748 #endif |
2750 VirtualFrame::SpilledScope spilled_scope(frame_); | |
2751 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); | 2749 Comment cmnt(masm_, "[ SharedFunctionInfoLiteral"); |
2752 InstantiateFunction(node->shared_function_info()); | 2750 InstantiateFunction(node->shared_function_info()); |
2753 ASSERT_EQ(original_height + 1, frame_->height()); | 2751 ASSERT_EQ(original_height + 1, frame_->height()); |
2754 } | 2752 } |
2755 | 2753 |
2756 | 2754 |
2757 void CodeGenerator::VisitConditional(Conditional* node) { | 2755 void CodeGenerator::VisitConditional(Conditional* node) { |
2758 #ifdef DEBUG | 2756 #ifdef DEBUG |
2759 int original_height = frame_->height(); | 2757 int original_height = frame_->height(); |
2760 #endif | 2758 #endif |
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4034 // Update the write barrier. | 4032 // Update the write barrier. |
4035 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); | 4033 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); |
4036 __ RecordWrite(r1, r2, r3); | 4034 __ RecordWrite(r1, r2, r3); |
4037 // Leave. | 4035 // Leave. |
4038 leave.Bind(); | 4036 leave.Bind(); |
4039 frame_->EmitPush(r0); | 4037 frame_->EmitPush(r0); |
4040 } | 4038 } |
4041 | 4039 |
4042 | 4040 |
4043 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 4041 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
4044 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4045 ASSERT(args->length() == 1); | 4042 ASSERT(args->length() == 1); |
4046 LoadAndSpill(args->at(0)); | 4043 Load(args->at(0)); |
4047 frame_->EmitPop(r0); | 4044 Register reg = frame_->PopToRegister(); |
4048 __ tst(r0, Operand(kSmiTagMask)); | 4045 __ tst(reg, Operand(kSmiTagMask)); |
4049 cc_reg_ = eq; | 4046 cc_reg_ = eq; |
4050 } | 4047 } |
4051 | 4048 |
4052 | 4049 |
4053 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { | 4050 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { |
4054 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4055 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. | 4051 // See comment in CodeGenerator::GenerateLog in codegen-ia32.cc. |
4056 ASSERT_EQ(args->length(), 3); | 4052 ASSERT_EQ(args->length(), 3); |
4057 #ifdef ENABLE_LOGGING_AND_PROFILING | 4053 #ifdef ENABLE_LOGGING_AND_PROFILING |
4058 if (ShouldGenerateLog(args->at(0))) { | 4054 if (ShouldGenerateLog(args->at(0))) { |
4059 LoadAndSpill(args->at(1)); | 4055 Load(args->at(1)); |
4060 LoadAndSpill(args->at(2)); | 4056 Load(args->at(2)); |
| 4057 frame_->SpillAll(); |
| 4058 VirtualFrame::SpilledScope spilled_scope(frame_); |
4061 __ CallRuntime(Runtime::kLog, 2); | 4059 __ CallRuntime(Runtime::kLog, 2); |
4062 } | 4060 } |
4063 #endif | 4061 #endif |
4064 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 4062 frame_->EmitPushRoot(Heap::kUndefinedValueRootIndex); |
4065 frame_->EmitPush(r0); | |
4066 } | 4063 } |
4067 | 4064 |
4068 | 4065 |
4069 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 4066 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
4070 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4071 ASSERT(args->length() == 1); | 4067 ASSERT(args->length() == 1); |
4072 LoadAndSpill(args->at(0)); | 4068 Load(args->at(0)); |
4073 frame_->EmitPop(r0); | 4069 Register reg = frame_->PopToRegister(); |
4074 __ tst(r0, Operand(kSmiTagMask | 0x80000000u)); | 4070 __ tst(reg, Operand(kSmiTagMask | 0x80000000u)); |
4075 cc_reg_ = eq; | 4071 cc_reg_ = eq; |
4076 } | 4072 } |
4077 | 4073 |
4078 | 4074 |
4079 // Generates the Math.pow method - currently just calls runtime. | 4075 // Generates the Math.pow method - currently just calls runtime. |
4080 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { | 4076 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { |
4081 ASSERT(args->length() == 2); | 4077 ASSERT(args->length() == 2); |
4082 Load(args->at(0)); | 4078 Load(args->at(0)); |
4083 Load(args->at(1)); | 4079 Load(args->at(1)); |
4084 frame_->CallRuntime(Runtime::kMath_pow, 2); | 4080 frame_->CallRuntime(Runtime::kMath_pow, 2); |
(...skipping 10 matching lines...) Expand all Loading... |
4095 } | 4091 } |
4096 | 4092 |
4097 | 4093 |
4098 // This generates code that performs a charCodeAt() call or returns | 4094 // This generates code that performs a charCodeAt() call or returns |
4099 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | 4095 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. |
4100 // It can handle flat, 8 and 16 bit characters and cons strings where the | 4096 // It can handle flat, 8 and 16 bit characters and cons strings where the |
4101 // answer is found in the left hand branch of the cons. The slow case will | 4097 // answer is found in the left hand branch of the cons. The slow case will |
4102 // flatten the string, which will ensure that the answer is in the left hand | 4098 // flatten the string, which will ensure that the answer is in the left hand |
4103 // side the next time around. | 4099 // side the next time around. |
4104 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 4100 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { |
4105 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4106 ASSERT(args->length() == 2); | 4101 ASSERT(args->length() == 2); |
4107 Comment(masm_, "[ GenerateFastCharCodeAt"); | 4102 Comment(masm_, "[ GenerateFastCharCodeAt"); |
4108 | 4103 |
4109 LoadAndSpill(args->at(0)); | 4104 Load(args->at(0)); |
4110 LoadAndSpill(args->at(1)); | 4105 Load(args->at(1)); |
4111 frame_->EmitPop(r1); // Index. | 4106 Register index = frame_->PopToRegister(); // Index. |
4112 frame_->EmitPop(r2); // String. | 4107 Register string = frame_->PopToRegister(index); // String. |
| 4108 Register result = VirtualFrame::scratch0(); |
| 4109 Register scratch = VirtualFrame::scratch1(); |
4113 | 4110 |
4114 Label slow_case; | 4111 Label slow_case; |
4115 Label exit; | 4112 Label exit; |
4116 StringHelper::GenerateFastCharCodeAt(masm_, | 4113 StringHelper::GenerateFastCharCodeAt(masm_, |
4117 r2, | 4114 string, |
4118 r1, | 4115 index, |
4119 r3, | 4116 scratch, |
4120 r0, | 4117 result, |
4121 &slow_case, | 4118 &slow_case, |
4122 &slow_case, | 4119 &slow_case, |
4123 &slow_case, | 4120 &slow_case, |
4124 &slow_case); | 4121 &slow_case); |
4125 __ jmp(&exit); | 4122 __ jmp(&exit); |
4126 | 4123 |
4127 __ bind(&slow_case); | 4124 __ bind(&slow_case); |
4128 // Move the undefined value into the result register, which will | 4125 // Move the undefined value into the result register, which will |
4129 // trigger the slow case. | 4126 // trigger the slow case. |
4130 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 4127 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
4131 | 4128 |
4132 __ bind(&exit); | 4129 __ bind(&exit); |
4133 frame_->EmitPush(r0); | 4130 frame_->EmitPush(result); |
4134 } | 4131 } |
4135 | 4132 |
4136 | 4133 |
4137 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { | 4134 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { |
4138 Comment(masm_, "[ GenerateCharFromCode"); | 4135 Comment(masm_, "[ GenerateCharFromCode"); |
4139 ASSERT(args->length() == 1); | 4136 ASSERT(args->length() == 1); |
4140 | 4137 |
4141 Register code = r1; | 4138 Register code = r1; |
4142 Register scratch = ip; | 4139 Register scratch = ip; |
4143 Register result = r0; | 4140 Register result = r0; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4244 __ tst(r0, Operand(kSmiTagMask)); | 4241 __ tst(r0, Operand(kSmiTagMask)); |
4245 false_target()->Branch(eq); | 4242 false_target()->Branch(eq); |
4246 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 4243 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
4247 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 4244 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
4248 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 4245 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
4249 cc_reg_ = ne; | 4246 cc_reg_ = ne; |
4250 } | 4247 } |
4251 | 4248 |
4252 | 4249 |
4253 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { | 4250 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { |
4254 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4255 ASSERT(args->length() == 0); | 4251 ASSERT(args->length() == 0); |
4256 | 4252 |
| 4253 Register scratch0 = VirtualFrame::scratch0(); |
| 4254 Register scratch1 = VirtualFrame::scratch1(); |
4257 // Get the frame pointer for the calling frame. | 4255 // Get the frame pointer for the calling frame. |
4258 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 4256 __ ldr(scratch0, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
4259 | 4257 |
4260 // Skip the arguments adaptor frame if it exists. | 4258 // Skip the arguments adaptor frame if it exists. |
4261 Label check_frame_marker; | 4259 __ ldr(scratch1, |
4262 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 4260 MemOperand(scratch0, StandardFrameConstants::kContextOffset)); |
4263 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 4261 __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
4264 __ b(ne, &check_frame_marker); | 4262 __ ldr(scratch0, |
4265 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | 4263 MemOperand(scratch0, StandardFrameConstants::kCallerFPOffset), eq); |
4266 | 4264 |
4267 // Check the marker in the calling frame. | 4265 // Check the marker in the calling frame. |
4268 __ bind(&check_frame_marker); | 4266 __ ldr(scratch1, |
4269 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); | 4267 MemOperand(scratch0, StandardFrameConstants::kMarkerOffset)); |
4270 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 4268 __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
4271 cc_reg_ = eq; | 4269 cc_reg_ = eq; |
4272 } | 4270 } |
4273 | 4271 |
4274 | 4272 |
4275 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 4273 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
4276 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4277 ASSERT(args->length() == 0); | 4274 ASSERT(args->length() == 0); |
4278 | 4275 |
4279 Label exit; | 4276 Register tos = frame_->GetTOSRegister(); |
| 4277 Register scratch0 = VirtualFrame::scratch0(); |
| 4278 Register scratch1 = VirtualFrame::scratch1(); |
| 4279 |
| 4280 // Check if the calling frame is an arguments adaptor frame. |
| 4281 __ ldr(scratch0, |
| 4282 MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 4283 __ ldr(scratch1, |
| 4284 MemOperand(scratch0, StandardFrameConstants::kContextOffset)); |
| 4285 __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
4280 | 4286 |
4281 // Get the number of formal parameters. | 4287 // Get the number of formal parameters. |
4282 __ mov(r0, Operand(Smi::FromInt(scope()->num_parameters()))); | 4288 __ mov(tos, Operand(Smi::FromInt(scope()->num_parameters())), LeaveCC, ne); |
4283 | |
4284 // Check if the calling frame is an arguments adaptor frame. | |
4285 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | |
4286 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); | |
4287 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
4288 __ b(ne, &exit); | |
4289 | 4289 |
4290 // Arguments adaptor case: Read the arguments length from the | 4290 // Arguments adaptor case: Read the arguments length from the |
4291 // adaptor frame. | 4291 // adaptor frame. |
4292 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 4292 __ ldr(tos, |
| 4293 MemOperand(scratch0, ArgumentsAdaptorFrameConstants::kLengthOffset), |
| 4294 eq); |
4293 | 4295 |
4294 __ bind(&exit); | 4296 frame_->EmitPush(tos); |
4295 frame_->EmitPush(r0); | |
4296 } | 4297 } |
4297 | 4298 |
4298 | 4299 |
4299 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { | 4300 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { |
4300 VirtualFrame::SpilledScope spilled_scope(frame_); | 4301 VirtualFrame::SpilledScope spilled_scope(frame_); |
4301 ASSERT(args->length() == 1); | 4302 ASSERT(args->length() == 1); |
4302 | 4303 |
4303 // Satisfy contract with ArgumentsAccessStub: | 4304 // Satisfy contract with ArgumentsAccessStub: |
4304 // Load the key into r1 and the formal parameters count into r0. | 4305 // Load the key into r1 and the formal parameters count into r0. |
4305 LoadAndSpill(args->at(0)); | 4306 LoadAndSpill(args->at(0)); |
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4724 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | 4725 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
4725 ASSERT_EQ(args->length(), 1); | 4726 ASSERT_EQ(args->length(), 1); |
4726 // Load the argument on the stack and jump to the runtime. | 4727 // Load the argument on the stack and jump to the runtime. |
4727 Load(args->at(0)); | 4728 Load(args->at(0)); |
4728 frame_->CallRuntime(Runtime::kMath_cos, 1); | 4729 frame_->CallRuntime(Runtime::kMath_cos, 1); |
4729 frame_->EmitPush(r0); | 4730 frame_->EmitPush(r0); |
4730 } | 4731 } |
4731 | 4732 |
4732 | 4733 |
4733 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 4734 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
4734 VirtualFrame::SpilledScope spilled_scope(frame_); | |
4735 ASSERT(args->length() == 2); | 4735 ASSERT(args->length() == 2); |
4736 | 4736 |
4737 // Load the two objects into registers and perform the comparison. | 4737 // Load the two objects into registers and perform the comparison. |
4738 LoadAndSpill(args->at(0)); | 4738 Load(args->at(0)); |
4739 LoadAndSpill(args->at(1)); | 4739 Load(args->at(1)); |
4740 frame_->EmitPop(r0); | 4740 Register lhs = frame_->PopToRegister(); |
4741 frame_->EmitPop(r1); | 4741 Register rhs = frame_->PopToRegister(lhs); |
4742 __ cmp(r0, r1); | 4742 __ cmp(lhs, rhs); |
4743 cc_reg_ = eq; | 4743 cc_reg_ = eq; |
4744 } | 4744 } |
4745 | 4745 |
4746 | 4746 |
4747 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 4747 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
4748 #ifdef DEBUG | 4748 #ifdef DEBUG |
4749 int original_height = frame_->height(); | 4749 int original_height = frame_->height(); |
4750 #endif | 4750 #endif |
4751 VirtualFrame::SpilledScope spilled_scope(frame_); | 4751 VirtualFrame::SpilledScope spilled_scope(frame_); |
4752 if (CheckForInlineRuntimeCall(node)) { | 4752 if (CheckForInlineRuntimeCall(node)) { |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5031 // operators must yield the result of one of the two expressions | 5031 // operators must yield the result of one of the two expressions |
5032 // before any ToBoolean() conversions. This means that the value | 5032 // before any ToBoolean() conversions. This means that the value |
5033 // produced by a && or || operator is not necessarily a boolean. | 5033 // produced by a && or || operator is not necessarily a boolean. |
5034 | 5034 |
5035 // NOTE: If the left hand side produces a materialized value (not in | 5035 // NOTE: If the left hand side produces a materialized value (not in |
5036 // the CC register), we force the right hand side to do the | 5036 // the CC register), we force the right hand side to do the |
5037 // same. This is necessary because we may have to branch to the exit | 5037 // same. This is necessary because we may have to branch to the exit |
5038 // after evaluating the left hand side (due to the shortcut | 5038 // after evaluating the left hand side (due to the shortcut |
5039 // semantics), but the compiler must (statically) know if the result | 5039 // semantics), but the compiler must (statically) know if the result |
5040 // of compiling the binary operation is materialized or not. | 5040 // of compiling the binary operation is materialized or not. |
| 5041 VirtualFrame::SpilledScope spilled_scope(frame_); |
5041 if (node->op() == Token::AND) { | 5042 if (node->op() == Token::AND) { |
5042 JumpTarget is_true; | 5043 JumpTarget is_true; |
5043 LoadConditionAndSpill(node->left(), | 5044 LoadConditionAndSpill(node->left(), |
5044 &is_true, | 5045 &is_true, |
5045 false_target(), | 5046 false_target(), |
5046 false); | 5047 false); |
5047 if (has_valid_frame() && !has_cc()) { | 5048 if (has_valid_frame() && !has_cc()) { |
5048 // The left-hand side result is on top of the virtual frame. | 5049 // The left-hand side result is on top of the virtual frame. |
5049 JumpTarget pop_and_continue; | 5050 JumpTarget pop_and_continue; |
5050 JumpTarget exit; | 5051 JumpTarget exit; |
5051 | 5052 |
5052 __ ldr(r0, frame_->Top()); // Duplicate the stack top. | 5053 frame_->Dup(); |
5053 frame_->EmitPush(r0); | |
5054 // Avoid popping the result if it converts to 'false' using the | 5054 // Avoid popping the result if it converts to 'false' using the |
5055 // standard ToBoolean() conversion as described in ECMA-262, | 5055 // standard ToBoolean() conversion as described in ECMA-262, |
5056 // section 9.2, page 30. | 5056 // section 9.2, page 30. |
5057 ToBoolean(&pop_and_continue, &exit); | 5057 ToBoolean(&pop_and_continue, &exit); |
5058 Branch(false, &exit); | 5058 Branch(false, &exit); |
5059 | 5059 |
5060 // Pop the result of evaluating the first part. | 5060 // Pop the result of evaluating the first part. |
5061 pop_and_continue.Bind(); | 5061 pop_and_continue.Bind(); |
5062 frame_->EmitPop(r0); | 5062 frame_->Pop(); |
5063 | 5063 |
5064 // Evaluate right side expression. | 5064 // Evaluate right side expression. |
5065 is_true.Bind(); | 5065 is_true.Bind(); |
5066 LoadAndSpill(node->right()); | 5066 LoadAndSpill(node->right()); |
5067 | 5067 |
5068 // Exit (always with a materialized value). | 5068 // Exit (always with a materialized value). |
5069 exit.Bind(); | 5069 exit.Bind(); |
5070 } else if (has_cc() || is_true.is_linked()) { | 5070 } else if (has_cc() || is_true.is_linked()) { |
5071 // The left-hand side is either (a) partially compiled to | 5071 // The left-hand side is either (a) partially compiled to |
5072 // control flow with a final branch left to emit or (b) fully | 5072 // control flow with a final branch left to emit or (b) fully |
(...skipping 16 matching lines...) Expand all Loading... |
5089 JumpTarget is_false; | 5089 JumpTarget is_false; |
5090 LoadConditionAndSpill(node->left(), | 5090 LoadConditionAndSpill(node->left(), |
5091 true_target(), | 5091 true_target(), |
5092 &is_false, | 5092 &is_false, |
5093 false); | 5093 false); |
5094 if (has_valid_frame() && !has_cc()) { | 5094 if (has_valid_frame() && !has_cc()) { |
5095 // The left-hand side result is on top of the virtual frame. | 5095 // The left-hand side result is on top of the virtual frame. |
5096 JumpTarget pop_and_continue; | 5096 JumpTarget pop_and_continue; |
5097 JumpTarget exit; | 5097 JumpTarget exit; |
5098 | 5098 |
5099 __ ldr(r0, frame_->Top()); | 5099 frame_->Dup(); |
5100 frame_->EmitPush(r0); | |
5101 // Avoid popping the result if it converts to 'true' using the | 5100 // Avoid popping the result if it converts to 'true' using the |
5102 // standard ToBoolean() conversion as described in ECMA-262, | 5101 // standard ToBoolean() conversion as described in ECMA-262, |
5103 // section 9.2, page 30. | 5102 // section 9.2, page 30. |
5104 ToBoolean(&exit, &pop_and_continue); | 5103 ToBoolean(&exit, &pop_and_continue); |
5105 Branch(true, &exit); | 5104 Branch(true, &exit); |
5106 | 5105 |
5107 // Pop the result of evaluating the first part. | 5106 // Pop the result of evaluating the first part. |
5108 pop_and_continue.Bind(); | 5107 pop_and_continue.Bind(); |
5109 frame_->EmitPop(r0); | 5108 frame_->Pop(); |
5110 | 5109 |
5111 // Evaluate right side expression. | 5110 // Evaluate right side expression. |
5112 is_false.Bind(); | 5111 is_false.Bind(); |
5113 LoadAndSpill(node->right()); | 5112 LoadAndSpill(node->right()); |
5114 | 5113 |
5115 // Exit (always with a materialized value). | 5114 // Exit (always with a materialized value). |
5116 exit.Bind(); | 5115 exit.Bind(); |
5117 } else if (has_cc() || is_false.is_linked()) { | 5116 } else if (has_cc() || is_false.is_linked()) { |
5118 // The left-hand side is either (a) partially compiled to | 5117 // The left-hand side is either (a) partially compiled to |
5119 // control flow with a final branch left to emit or (b) fully | 5118 // control flow with a final branch left to emit or (b) fully |
(...skipping 14 matching lines...) Expand all Loading... |
5134 } | 5133 } |
5135 | 5134 |
5136 | 5135 |
5137 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 5136 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
5138 #ifdef DEBUG | 5137 #ifdef DEBUG |
5139 int original_height = frame_->height(); | 5138 int original_height = frame_->height(); |
5140 #endif | 5139 #endif |
5141 Comment cmnt(masm_, "[ BinaryOperation"); | 5140 Comment cmnt(masm_, "[ BinaryOperation"); |
5142 | 5141 |
5143 if (node->op() == Token::AND || node->op() == Token::OR) { | 5142 if (node->op() == Token::AND || node->op() == Token::OR) { |
5144 VirtualFrame::SpilledScope spilled_scope(frame_); | |
5145 GenerateLogicalBooleanOperation(node); | 5143 GenerateLogicalBooleanOperation(node); |
5146 } else { | 5144 } else { |
5147 // Optimize for the case where (at least) one of the expressions | 5145 // Optimize for the case where (at least) one of the expressions |
5148 // is a literal small integer. | 5146 // is a literal small integer. |
5149 Literal* lliteral = node->left()->AsLiteral(); | 5147 Literal* lliteral = node->left()->AsLiteral(); |
5150 Literal* rliteral = node->right()->AsLiteral(); | 5148 Literal* rliteral = node->right()->AsLiteral(); |
5151 // NOTE: The code below assumes that the slow cases (calls to runtime) | 5149 // NOTE: The code below assumes that the slow cases (calls to runtime) |
5152 // never return a constant/immutable object. | 5150 // never return a constant/immutable object. |
5153 bool overwrite_left = | 5151 bool overwrite_left = |
5154 (node->left()->AsBinaryOperation() != NULL && | 5152 (node->left()->AsBinaryOperation() != NULL && |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5187 ASSERT(!has_valid_frame() || | 5185 ASSERT(!has_valid_frame() || |
5188 (has_cc() && frame_->height() == original_height) || | 5186 (has_cc() && frame_->height() == original_height) || |
5189 (!has_cc() && frame_->height() == original_height + 1)); | 5187 (!has_cc() && frame_->height() == original_height + 1)); |
5190 } | 5188 } |
5191 | 5189 |
5192 | 5190 |
5193 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 5191 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
5194 #ifdef DEBUG | 5192 #ifdef DEBUG |
5195 int original_height = frame_->height(); | 5193 int original_height = frame_->height(); |
5196 #endif | 5194 #endif |
5197 VirtualFrame::SpilledScope spilled_scope(frame_); | 5195 frame_->EmitPush(MemOperand(frame_->Function())); |
5198 __ ldr(r0, frame_->Function()); | |
5199 frame_->EmitPush(r0); | |
5200 ASSERT_EQ(original_height + 1, frame_->height()); | 5196 ASSERT_EQ(original_height + 1, frame_->height()); |
5201 } | 5197 } |
5202 | 5198 |
5203 | 5199 |
5204 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 5200 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
5205 #ifdef DEBUG | 5201 #ifdef DEBUG |
5206 int original_height = frame_->height(); | 5202 int original_height = frame_->height(); |
5207 #endif | 5203 #endif |
5208 Comment cmnt(masm_, "[ CompareOperation"); | 5204 Comment cmnt(masm_, "[ CompareOperation"); |
5209 | 5205 |
(...skipping 4825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10035 __ bind(&string_add_runtime); | 10031 __ bind(&string_add_runtime); |
10036 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10032 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10037 } | 10033 } |
10038 | 10034 |
10039 | 10035 |
10040 #undef __ | 10036 #undef __ |
10041 | 10037 |
10042 } } // namespace v8::internal | 10038 } } // namespace v8::internal |
10043 | 10039 |
10044 #endif // V8_TARGET_ARCH_ARM | 10040 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |