Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2048 if (can_overflow) { | 2048 if (can_overflow) { |
| 2049 DeoptimizeIf(vs, instr->environment()); | 2049 DeoptimizeIf(vs, instr->environment()); |
| 2050 } | 2050 } |
| 2051 } | 2051 } |
| 2052 | 2052 |
| 2053 | 2053 |
| 2054 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 2054 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 2055 LOperand* left = instr->left(); | 2055 LOperand* left = instr->left(); |
| 2056 LOperand* right = instr->right(); | 2056 LOperand* right = instr->right(); |
| 2057 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 2057 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 2058 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | |
| 2059 if (instr->hydrogen()->representation().IsInteger32()) { | 2058 if (instr->hydrogen()->representation().IsInteger32()) { |
| 2059 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | |
| 2060 Register left_reg = ToRegister(left); | 2060 Register left_reg = ToRegister(left); |
| 2061 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) | 2061 Operand right_op = (right->IsRegister() || right->IsConstantOperand()) |
| 2062 ? ToOperand(right) | 2062 ? ToOperand(right) |
| 2063 : Operand(EmitLoadRegister(right, ip)); | 2063 : Operand(EmitLoadRegister(right, ip)); |
| 2064 Register result_reg = ToRegister(instr->result()); | 2064 Register result_reg = ToRegister(instr->result()); |
| 2065 __ cmp(left_reg, right_op); | 2065 __ cmp(left_reg, right_op); |
| 2066 if (!result_reg.is(left_reg)) { | 2066 __ Move(result_reg, left_reg, condition); |
| 2067 __ mov(result_reg, left_reg, LeaveCC, condition); | |
| 2068 } | |
| 2069 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); | 2067 __ mov(result_reg, right_op, LeaveCC, NegateCondition(condition)); |
| 2070 } else { | 2068 } else { |
| 2071 ASSERT(instr->hydrogen()->representation().IsDouble()); | 2069 ASSERT(instr->hydrogen()->representation().IsDouble()); |
| 2072 DwVfpRegister left_reg = ToDoubleRegister(left); | 2070 DwVfpRegister left_reg = ToDoubleRegister(left); |
| 2073 DwVfpRegister right_reg = ToDoubleRegister(right); | 2071 DwVfpRegister right_reg = ToDoubleRegister(right); |
| 2074 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); | 2072 DwVfpRegister result_reg = ToDoubleRegister(instr->result()); |
| 2075 Label check_nan_left, check_zero, return_left, return_right, done; | 2073 Label result_is_nan, return_left, return_right, check_zero, done; |
| 2076 __ VFPCompareAndSetFlags(left_reg, right_reg); | 2074 __ VFPCompareAndSetFlags(left_reg, right_reg); |
| 2077 __ b(vs, &check_nan_left); | 2075 if (operation == HMathMinMax::kMathMin) { |
| 2078 __ b(eq, &check_zero); | 2076 __ b(mi, &return_left); |
| 2079 __ b(condition, &return_left); | 2077 __ b(gt, &return_right); |
| 2080 __ b(al, &return_right); | 2078 } else { |
| 2081 | 2079 __ b(mi, &return_right); |
| 2082 __ bind(&check_zero); | 2080 __ b(gt, &return_left); |
| 2081 } | |
| 2082 __ b(vs, &result_is_nan); | |
| 2083 // Left equals right => check for -0. | |
| 2083 __ VFPCompareAndSetFlags(left_reg, 0.0); | 2084 __ VFPCompareAndSetFlags(left_reg, 0.0); |
| 2084 __ b(ne, &return_left); // left == right != 0. | 2085 if (left_reg.is(result_reg) || right_reg.is(result_reg)) { |
| 2086 __ b(ne, &done); // left == right != 0. | |
| 2087 } else { | |
| 2088 __ b(ne, &return_left); // left == right != 0. | |
| 2089 } | |
| 2085 // At this point, both left and right are either 0 or -0. | 2090 // At this point, both left and right are either 0 or -0. |
| 2086 if (operation == HMathMinMax::kMathMin) { | 2091 if (operation == HMathMinMax::kMathMin) { |
| 2087 // We could use a single 'vorr' instruction here if we had NEON support. | 2092 // We could use a single 'vorr' instruction here if we had NEON support. |
| 2088 __ vneg(left_reg, left_reg); | 2093 __ vneg(left_reg, left_reg); |
| 2089 __ vsub(result_reg, left_reg, right_reg); | 2094 __ vsub(result_reg, left_reg, right_reg); |
| 2090 __ vneg(result_reg, result_reg); | 2095 __ vneg(result_reg, result_reg); |
| 2091 } else { | 2096 } else { |
| 2092 // Since we operate on +0 and/or -0, vadd and vand have the same effect; | 2097 // Since we operate on +0 and/or -0, vadd and vand have the same effect; |
| 2093 // the decision for vadd is easy because vand is a NEON instruction. | 2098 // the decision for vadd is easy because vand is a NEON instruction. |
| 2094 __ vadd(result_reg, left_reg, right_reg); | 2099 __ vadd(result_reg, left_reg, right_reg); |
| 2095 } | 2100 } |
| 2096 __ b(al, &done); | 2101 __ b(&done); |
| 2097 | 2102 |
| 2098 __ bind(&check_nan_left); | 2103 __ bind(&result_is_nan); |
| 2099 __ VFPCompareAndSetFlags(left_reg, left_reg); | 2104 __ vadd(result_reg, left_reg, right_reg); |
| 2100 __ b(vs, &return_left); // left == NaN. | 2105 __ b(&done); |
| 2106 | |
| 2101 __ bind(&return_right); | 2107 __ bind(&return_right); |
| 2102 if (!right_reg.is(result_reg)) { | 2108 __ Move(result_reg, right_reg); |
| 2103 __ vmov(result_reg, right_reg); | 2109 if (!left_reg.is(result_reg)) { |
|
ulan
2013/04/17 14:30:41
Why do we need this "if" here?
| |
| 2110 __ b(&done); | |
| 2104 } | 2111 } |
| 2105 __ b(al, &done); | |
| 2106 | 2112 |
| 2107 __ bind(&return_left); | 2113 __ bind(&return_left); |
| 2108 if (!left_reg.is(result_reg)) { | 2114 __ Move(result_reg, left_reg); |
| 2109 __ vmov(result_reg, left_reg); | 2115 |
| 2110 } | |
| 2111 __ bind(&done); | 2116 __ bind(&done); |
| 2112 } | 2117 } |
| 2113 } | 2118 } |
| 2114 | 2119 |
| 2115 | 2120 |
| 2116 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2121 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 2117 DwVfpRegister left = ToDoubleRegister(instr->left()); | 2122 DwVfpRegister left = ToDoubleRegister(instr->left()); |
| 2118 DwVfpRegister right = ToDoubleRegister(instr->right()); | 2123 DwVfpRegister right = ToDoubleRegister(instr->right()); |
| 2119 DwVfpRegister result = ToDoubleRegister(instr->result()); | 2124 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 2120 switch (instr->op()) { | 2125 switch (instr->op()) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2198 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2203 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2199 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2204 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2200 | 2205 |
| 2201 Representation r = instr->hydrogen()->value()->representation(); | 2206 Representation r = instr->hydrogen()->value()->representation(); |
| 2202 if (r.IsInteger32()) { | 2207 if (r.IsInteger32()) { |
| 2203 Register reg = ToRegister(instr->value()); | 2208 Register reg = ToRegister(instr->value()); |
| 2204 __ cmp(reg, Operand::Zero()); | 2209 __ cmp(reg, Operand::Zero()); |
| 2205 EmitBranch(true_block, false_block, ne); | 2210 EmitBranch(true_block, false_block, ne); |
| 2206 } else if (r.IsDouble()) { | 2211 } else if (r.IsDouble()) { |
| 2207 DwVfpRegister reg = ToDoubleRegister(instr->value()); | 2212 DwVfpRegister reg = ToDoubleRegister(instr->value()); |
| 2208 Register scratch = scratch0(); | |
| 2209 | |
| 2210 // Test the double value. Zero and NaN are false. | 2213 // Test the double value. Zero and NaN are false. |
| 2211 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); | 2214 __ VFPCompareAndSetFlags(reg, 0.0); |
| 2212 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); | 2215 __ cmp(r0, r0, vs); // If NaN, set the Z flag. |
| 2213 EmitBranch(true_block, false_block, eq); | 2216 EmitBranch(true_block, false_block, ne); |
| 2214 } else { | 2217 } else { |
| 2215 ASSERT(r.IsTagged()); | 2218 ASSERT(r.IsTagged()); |
| 2216 Register reg = ToRegister(instr->value()); | 2219 Register reg = ToRegister(instr->value()); |
| 2217 HType type = instr->hydrogen()->value()->type(); | 2220 HType type = instr->hydrogen()->value()->type(); |
| 2218 if (type.IsBoolean()) { | 2221 if (type.IsBoolean()) { |
| 2219 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 2222 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 2220 EmitBranch(true_block, false_block, eq); | 2223 EmitBranch(true_block, false_block, eq); |
| 2221 } else if (type.IsSmi()) { | 2224 } else if (type.IsSmi()) { |
| 2222 __ cmp(reg, Operand::Zero()); | 2225 __ cmp(reg, Operand::Zero()); |
| 2223 EmitBranch(true_block, false_block, ne); | 2226 EmitBranch(true_block, false_block, ne); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2295 } | 2298 } |
| 2296 | 2299 |
| 2297 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2300 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 2298 // heap number -> false iff +0, -0, or NaN. | 2301 // heap number -> false iff +0, -0, or NaN. |
| 2299 DwVfpRegister dbl_scratch = double_scratch0(); | 2302 DwVfpRegister dbl_scratch = double_scratch0(); |
| 2300 Label not_heap_number; | 2303 Label not_heap_number; |
| 2301 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); | 2304 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); |
| 2302 __ b(ne, ¬_heap_number); | 2305 __ b(ne, ¬_heap_number); |
| 2303 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); | 2306 __ vldr(dbl_scratch, FieldMemOperand(reg, HeapNumber::kValueOffset)); |
| 2304 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2307 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
| 2305 __ b(vs, false_label); // NaN -> false. | 2308 __ cmp(r0, r0, vs); // NaN -> false. |
| 2306 __ b(eq, false_label); // +0, -0 -> false. | 2309 __ b(eq, false_label); // +0, -0 -> false. |
| 2307 __ b(true_label); | 2310 __ b(true_label); |
| 2308 __ bind(¬_heap_number); | 2311 __ bind(¬_heap_number); |
| 2309 } | 2312 } |
| 2310 | 2313 |
| 2311 // We've seen something for the first time -> deopt. | 2314 // We've seen something for the first time -> deopt. |
| 2312 DeoptimizeIf(al, instr->environment()); | 2315 DeoptimizeIf(al, instr->environment()); |
| 2313 } | 2316 } |
| 2314 } | 2317 } |
| 2315 } | 2318 } |
| (...skipping 3696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6012 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 6015 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 6013 __ ldr(result, FieldMemOperand(scratch, | 6016 __ ldr(result, FieldMemOperand(scratch, |
| 6014 FixedArray::kHeaderSize - kPointerSize)); | 6017 FixedArray::kHeaderSize - kPointerSize)); |
| 6015 __ bind(&done); | 6018 __ bind(&done); |
| 6016 } | 6019 } |
| 6017 | 6020 |
| 6018 | 6021 |
| 6019 #undef __ | 6022 #undef __ |
| 6020 | 6023 |
| 6021 } } // namespace v8::internal | 6024 } } // namespace v8::internal |
| OLD | NEW |