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 2069 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2080 | 2080 |
2081 | 2081 |
2082 int LCodeGen::GetNextEmittedBlock() const { | 2082 int LCodeGen::GetNextEmittedBlock() const { |
2083 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 2083 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
2084 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 2084 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
2085 } | 2085 } |
2086 return -1; | 2086 return -1; |
2087 } | 2087 } |
2088 | 2088 |
2089 | 2089 |
2090 void LCodeGen::EmitBranch(int left_block, int right_block, Condition cc) { | 2090 template<class InstrType> |
| 2091 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 2092 int right_block = instr->FalseDestination(chunk_); |
| 2093 int left_block = instr->TrueDestination(chunk_); |
| 2094 |
2091 int next_block = GetNextEmittedBlock(); | 2095 int next_block = GetNextEmittedBlock(); |
2092 right_block = chunk_->LookupDestination(right_block); | |
2093 left_block = chunk_->LookupDestination(left_block); | |
2094 | 2096 |
2095 if (right_block == left_block) { | 2097 if (right_block == left_block) { |
2096 EmitGoto(left_block); | 2098 EmitGoto(left_block); |
2097 } else if (left_block == next_block) { | 2099 } else if (left_block == next_block) { |
2098 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); | 2100 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); |
2099 } else if (right_block == next_block) { | 2101 } else if (right_block == next_block) { |
2100 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 2102 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
2101 } else { | 2103 } else { |
2102 __ j(cc, chunk_->GetAssemblyLabel(left_block)); | 2104 __ j(cc, chunk_->GetAssemblyLabel(left_block)); |
2103 __ jmp(chunk_->GetAssemblyLabel(right_block)); | 2105 __ jmp(chunk_->GetAssemblyLabel(right_block)); |
2104 } | 2106 } |
2105 } | 2107 } |
2106 | 2108 |
2107 | 2109 |
2108 void LCodeGen::DoBranch(LBranch* instr) { | 2110 void LCodeGen::DoBranch(LBranch* instr) { |
2109 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2110 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2111 | |
2112 Representation r = instr->hydrogen()->value()->representation(); | 2111 Representation r = instr->hydrogen()->value()->representation(); |
2113 if (r.IsSmiOrInteger32()) { | 2112 if (r.IsSmiOrInteger32()) { |
2114 ASSERT(!info()->IsStub()); | 2113 ASSERT(!info()->IsStub()); |
2115 Register reg = ToRegister(instr->value()); | 2114 Register reg = ToRegister(instr->value()); |
2116 __ test(reg, Operand(reg)); | 2115 __ test(reg, Operand(reg)); |
2117 EmitBranch(true_block, false_block, not_zero); | 2116 EmitBranch(instr, not_zero); |
2118 } else if (r.IsDouble()) { | 2117 } else if (r.IsDouble()) { |
2119 ASSERT(!info()->IsStub()); | 2118 ASSERT(!info()->IsStub()); |
2120 CpuFeatureScope scope(masm(), SSE2); | 2119 CpuFeatureScope scope(masm(), SSE2); |
2121 XMMRegister reg = ToDoubleRegister(instr->value()); | 2120 XMMRegister reg = ToDoubleRegister(instr->value()); |
2122 __ xorps(xmm0, xmm0); | 2121 __ xorps(xmm0, xmm0); |
2123 __ ucomisd(reg, xmm0); | 2122 __ ucomisd(reg, xmm0); |
2124 EmitBranch(true_block, false_block, not_equal); | 2123 EmitBranch(instr, not_equal); |
2125 } else { | 2124 } else { |
2126 ASSERT(r.IsTagged()); | 2125 ASSERT(r.IsTagged()); |
2127 Register reg = ToRegister(instr->value()); | 2126 Register reg = ToRegister(instr->value()); |
2128 HType type = instr->hydrogen()->value()->type(); | 2127 HType type = instr->hydrogen()->value()->type(); |
2129 if (type.IsBoolean()) { | 2128 if (type.IsBoolean()) { |
2130 ASSERT(!info()->IsStub()); | 2129 ASSERT(!info()->IsStub()); |
2131 __ cmp(reg, factory()->true_value()); | 2130 __ cmp(reg, factory()->true_value()); |
2132 EmitBranch(true_block, false_block, equal); | 2131 EmitBranch(instr, equal); |
2133 } else if (type.IsSmi()) { | 2132 } else if (type.IsSmi()) { |
2134 ASSERT(!info()->IsStub()); | 2133 ASSERT(!info()->IsStub()); |
2135 __ test(reg, Operand(reg)); | 2134 __ test(reg, Operand(reg)); |
2136 EmitBranch(true_block, false_block, not_equal); | 2135 EmitBranch(instr, not_equal); |
2137 } else { | 2136 } else { |
2138 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
2139 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2140 | |
2141 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2137 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
2142 // Avoid deopts in the case where we've never executed this path before. | 2138 // Avoid deopts in the case where we've never executed this path before. |
2143 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 2139 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
2144 | 2140 |
2145 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 2141 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
2146 // undefined -> false. | 2142 // undefined -> false. |
2147 __ cmp(reg, factory()->undefined_value()); | 2143 __ cmp(reg, factory()->undefined_value()); |
2148 __ j(equal, false_label); | 2144 __ j(equal, instr->FalseLabel(chunk_)); |
2149 } | 2145 } |
2150 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 2146 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
2151 // true -> true. | 2147 // true -> true. |
2152 __ cmp(reg, factory()->true_value()); | 2148 __ cmp(reg, factory()->true_value()); |
2153 __ j(equal, true_label); | 2149 __ j(equal, instr->TrueLabel(chunk_)); |
2154 // false -> false. | 2150 // false -> false. |
2155 __ cmp(reg, factory()->false_value()); | 2151 __ cmp(reg, factory()->false_value()); |
2156 __ j(equal, false_label); | 2152 __ j(equal, instr->FalseLabel(chunk_)); |
2157 } | 2153 } |
2158 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 2154 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
2159 // 'null' -> false. | 2155 // 'null' -> false. |
2160 __ cmp(reg, factory()->null_value()); | 2156 __ cmp(reg, factory()->null_value()); |
2161 __ j(equal, false_label); | 2157 __ j(equal, instr->FalseLabel(chunk_)); |
2162 } | 2158 } |
2163 | 2159 |
2164 if (expected.Contains(ToBooleanStub::SMI)) { | 2160 if (expected.Contains(ToBooleanStub::SMI)) { |
2165 // Smis: 0 -> false, all other -> true. | 2161 // Smis: 0 -> false, all other -> true. |
2166 __ test(reg, Operand(reg)); | 2162 __ test(reg, Operand(reg)); |
2167 __ j(equal, false_label); | 2163 __ j(equal, instr->FalseLabel(chunk_)); |
2168 __ JumpIfSmi(reg, true_label); | 2164 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2169 } else if (expected.NeedsMap()) { | 2165 } else if (expected.NeedsMap()) { |
2170 // If we need a map later and have a Smi -> deopt. | 2166 // If we need a map later and have a Smi -> deopt. |
2171 __ test(reg, Immediate(kSmiTagMask)); | 2167 __ test(reg, Immediate(kSmiTagMask)); |
2172 DeoptimizeIf(zero, instr->environment()); | 2168 DeoptimizeIf(zero, instr->environment()); |
2173 } | 2169 } |
2174 | 2170 |
2175 Register map = no_reg; // Keep the compiler happy. | 2171 Register map = no_reg; // Keep the compiler happy. |
2176 if (expected.NeedsMap()) { | 2172 if (expected.NeedsMap()) { |
2177 map = ToRegister(instr->temp()); | 2173 map = ToRegister(instr->temp()); |
2178 ASSERT(!map.is(reg)); | 2174 ASSERT(!map.is(reg)); |
2179 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2175 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
2180 | 2176 |
2181 if (expected.CanBeUndetectable()) { | 2177 if (expected.CanBeUndetectable()) { |
2182 // Undetectable -> false. | 2178 // Undetectable -> false. |
2183 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 2179 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
2184 1 << Map::kIsUndetectable); | 2180 1 << Map::kIsUndetectable); |
2185 __ j(not_zero, false_label); | 2181 __ j(not_zero, instr->FalseLabel(chunk_)); |
2186 } | 2182 } |
2187 } | 2183 } |
2188 | 2184 |
2189 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 2185 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
2190 // spec object -> true. | 2186 // spec object -> true. |
2191 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 2187 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
2192 __ j(above_equal, true_label); | 2188 __ j(above_equal, instr->TrueLabel(chunk_)); |
2193 } | 2189 } |
2194 | 2190 |
2195 if (expected.Contains(ToBooleanStub::STRING)) { | 2191 if (expected.Contains(ToBooleanStub::STRING)) { |
2196 // String value -> false iff empty. | 2192 // String value -> false iff empty. |
2197 Label not_string; | 2193 Label not_string; |
2198 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 2194 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
2199 __ j(above_equal, ¬_string, Label::kNear); | 2195 __ j(above_equal, ¬_string, Label::kNear); |
2200 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2196 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
2201 __ j(not_zero, true_label); | 2197 __ j(not_zero, instr->TrueLabel(chunk_)); |
2202 __ jmp(false_label); | 2198 __ jmp(instr->FalseLabel(chunk_)); |
2203 __ bind(¬_string); | 2199 __ bind(¬_string); |
2204 } | 2200 } |
2205 | 2201 |
2206 if (expected.Contains(ToBooleanStub::SYMBOL)) { | 2202 if (expected.Contains(ToBooleanStub::SYMBOL)) { |
2207 // Symbol value -> true. | 2203 // Symbol value -> true. |
2208 __ CmpInstanceType(map, SYMBOL_TYPE); | 2204 __ CmpInstanceType(map, SYMBOL_TYPE); |
2209 __ j(equal, true_label); | 2205 __ j(equal, instr->TrueLabel(chunk_)); |
2210 } | 2206 } |
2211 | 2207 |
2212 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2208 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
2213 // heap number -> false iff +0, -0, or NaN. | 2209 // heap number -> false iff +0, -0, or NaN. |
2214 Label not_heap_number; | 2210 Label not_heap_number; |
2215 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2211 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
2216 factory()->heap_number_map()); | 2212 factory()->heap_number_map()); |
2217 __ j(not_equal, ¬_heap_number, Label::kNear); | 2213 __ j(not_equal, ¬_heap_number, Label::kNear); |
2218 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 2214 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
2219 CpuFeatureScope scope(masm(), SSE2); | 2215 CpuFeatureScope scope(masm(), SSE2); |
2220 __ xorps(xmm0, xmm0); | 2216 __ xorps(xmm0, xmm0); |
2221 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); | 2217 __ ucomisd(xmm0, FieldOperand(reg, HeapNumber::kValueOffset)); |
2222 } else { | 2218 } else { |
2223 __ fldz(); | 2219 __ fldz(); |
2224 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 2220 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
2225 __ FCmp(); | 2221 __ FCmp(); |
2226 } | 2222 } |
2227 __ j(zero, false_label); | 2223 __ j(zero, instr->FalseLabel(chunk_)); |
2228 __ jmp(true_label); | 2224 __ jmp(instr->TrueLabel(chunk_)); |
2229 __ bind(¬_heap_number); | 2225 __ bind(¬_heap_number); |
2230 } | 2226 } |
2231 | 2227 |
2232 // We've seen something for the first time -> deopt. | 2228 // We've seen something for the first time -> deopt. |
2233 DeoptimizeIf(no_condition, instr->environment()); | 2229 DeoptimizeIf(no_condition, instr->environment()); |
2234 } | 2230 } |
2235 } | 2231 } |
2236 } | 2232 } |
2237 | 2233 |
2238 | 2234 |
2239 void LCodeGen::EmitGoto(int block) { | 2235 void LCodeGen::EmitGoto(int block) { |
2240 if (!IsNextEmittedBlock(block)) { | 2236 if (!IsNextEmittedBlock(block)) { |
2241 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); | 2237 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
2242 } | 2238 } |
2243 } | 2239 } |
2244 | 2240 |
2245 | 2241 |
2246 void LCodeGen::DoGoto(LGoto* instr) { | 2242 void LCodeGen::DoGoto(LGoto* instr) { |
2247 EmitGoto(instr->block_id()); | 2243 EmitGoto(instr->block_id()); |
2248 } | 2244 } |
2249 | 2245 |
2250 | 2246 |
2251 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2247 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
(...skipping 20 matching lines...) Expand all Loading... |
2272 default: | 2268 default: |
2273 UNREACHABLE(); | 2269 UNREACHABLE(); |
2274 } | 2270 } |
2275 return cond; | 2271 return cond; |
2276 } | 2272 } |
2277 | 2273 |
2278 | 2274 |
2279 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 2275 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
2280 LOperand* left = instr->left(); | 2276 LOperand* left = instr->left(); |
2281 LOperand* right = instr->right(); | 2277 LOperand* right = instr->right(); |
2282 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2283 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2284 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 2278 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
2285 | 2279 |
2286 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2280 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
2287 // We can statically evaluate the comparison. | 2281 // We can statically evaluate the comparison. |
2288 double left_val = ToDouble(LConstantOperand::cast(left)); | 2282 double left_val = ToDouble(LConstantOperand::cast(left)); |
2289 double right_val = ToDouble(LConstantOperand::cast(right)); | 2283 double right_val = ToDouble(LConstantOperand::cast(right)); |
2290 int next_block = | 2284 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
2291 EvalComparison(instr->op(), left_val, right_val) ? true_block | 2285 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
2292 : false_block; | |
2293 EmitGoto(next_block); | 2286 EmitGoto(next_block); |
2294 } else { | 2287 } else { |
2295 if (instr->is_double()) { | 2288 if (instr->is_double()) { |
2296 CpuFeatureScope scope(masm(), SSE2); | 2289 CpuFeatureScope scope(masm(), SSE2); |
2297 // Don't base result on EFLAGS when a NaN is involved. Instead | 2290 // Don't base result on EFLAGS when a NaN is involved. Instead |
2298 // jump to the false block. | 2291 // jump to the false block. |
2299 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 2292 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
2300 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 2293 __ j(parity_even, instr->FalseLabel(chunk_)); |
2301 } else { | 2294 } else { |
2302 if (right->IsConstantOperand()) { | 2295 if (right->IsConstantOperand()) { |
2303 int32_t const_value = ToInteger32(LConstantOperand::cast(right)); | 2296 int32_t const_value = ToInteger32(LConstantOperand::cast(right)); |
2304 if (instr->hydrogen_value()->representation().IsSmi()) { | 2297 if (instr->hydrogen_value()->representation().IsSmi()) { |
2305 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value))); | 2298 __ cmp(ToOperand(left), Immediate(Smi::FromInt(const_value))); |
2306 } else { | 2299 } else { |
2307 __ cmp(ToOperand(left), Immediate(const_value)); | 2300 __ cmp(ToOperand(left), Immediate(const_value)); |
2308 } | 2301 } |
2309 } else if (left->IsConstantOperand()) { | 2302 } else if (left->IsConstantOperand()) { |
2310 int32_t const_value = ToInteger32(LConstantOperand::cast(left)); | 2303 int32_t const_value = ToInteger32(LConstantOperand::cast(left)); |
2311 if (instr->hydrogen_value()->representation().IsSmi()) { | 2304 if (instr->hydrogen_value()->representation().IsSmi()) { |
2312 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value))); | 2305 __ cmp(ToOperand(right), Immediate(Smi::FromInt(const_value))); |
2313 } else { | 2306 } else { |
2314 __ cmp(ToOperand(right), Immediate(const_value)); | 2307 __ cmp(ToOperand(right), Immediate(const_value)); |
2315 } | 2308 } |
2316 // We transposed the operands. Reverse the condition. | 2309 // We transposed the operands. Reverse the condition. |
2317 cc = ReverseCondition(cc); | 2310 cc = ReverseCondition(cc); |
2318 } else { | 2311 } else { |
2319 __ cmp(ToRegister(left), ToOperand(right)); | 2312 __ cmp(ToRegister(left), ToOperand(right)); |
2320 } | 2313 } |
2321 } | 2314 } |
2322 EmitBranch(true_block, false_block, cc); | 2315 EmitBranch(instr, cc); |
2323 } | 2316 } |
2324 } | 2317 } |
2325 | 2318 |
2326 | 2319 |
2327 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { | 2320 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { |
2328 Register left = ToRegister(instr->left()); | 2321 Register left = ToRegister(instr->left()); |
2329 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2330 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2331 | 2322 |
2332 if (instr->right()->IsConstantOperand()) { | 2323 if (instr->right()->IsConstantOperand()) { |
2333 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); | 2324 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); |
2334 __ CmpObject(left, right); | 2325 __ CmpObject(left, right); |
2335 } else { | 2326 } else { |
2336 Operand right = ToOperand(instr->right()); | 2327 Operand right = ToOperand(instr->right()); |
2337 __ cmp(left, right); | 2328 __ cmp(left, right); |
2338 } | 2329 } |
2339 EmitBranch(true_block, false_block, equal); | 2330 EmitBranch(instr, equal); |
2340 } | 2331 } |
2341 | 2332 |
2342 | 2333 |
2343 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { | 2334 void LCodeGen::DoCmpConstantEqAndBranch(LCmpConstantEqAndBranch* instr) { |
2344 Register left = ToRegister(instr->left()); | 2335 Register left = ToRegister(instr->left()); |
2345 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2346 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2347 | 2336 |
2348 __ cmp(left, instr->hydrogen()->right()); | 2337 __ cmp(left, instr->hydrogen()->right()); |
2349 EmitBranch(true_block, false_block, equal); | 2338 EmitBranch(instr, equal); |
2350 } | 2339 } |
2351 | 2340 |
2352 | 2341 |
2353 Condition LCodeGen::EmitIsObject(Register input, | 2342 Condition LCodeGen::EmitIsObject(Register input, |
2354 Register temp1, | 2343 Register temp1, |
2355 Label* is_not_object, | 2344 Label* is_not_object, |
2356 Label* is_object) { | 2345 Label* is_object) { |
2357 __ JumpIfSmi(input, is_not_object); | 2346 __ JumpIfSmi(input, is_not_object); |
2358 | 2347 |
2359 __ cmp(input, isolate()->factory()->null_value()); | 2348 __ cmp(input, isolate()->factory()->null_value()); |
(...skipping 10 matching lines...) Expand all Loading... |
2370 __ j(below, is_not_object); | 2359 __ j(below, is_not_object); |
2371 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 2360 __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
2372 return below_equal; | 2361 return below_equal; |
2373 } | 2362 } |
2374 | 2363 |
2375 | 2364 |
2376 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 2365 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
2377 Register reg = ToRegister(instr->value()); | 2366 Register reg = ToRegister(instr->value()); |
2378 Register temp = ToRegister(instr->temp()); | 2367 Register temp = ToRegister(instr->temp()); |
2379 | 2368 |
2380 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2369 Condition true_cond = EmitIsObject( |
2381 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2370 reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_)); |
2382 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
2383 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2384 | 2371 |
2385 Condition true_cond = EmitIsObject(reg, temp, false_label, true_label); | 2372 EmitBranch(instr, true_cond); |
2386 | |
2387 EmitBranch(true_block, false_block, true_cond); | |
2388 } | 2373 } |
2389 | 2374 |
2390 | 2375 |
2391 Condition LCodeGen::EmitIsString(Register input, | 2376 Condition LCodeGen::EmitIsString(Register input, |
2392 Register temp1, | 2377 Register temp1, |
2393 Label* is_not_string) { | 2378 Label* is_not_string) { |
2394 __ JumpIfSmi(input, is_not_string); | 2379 __ JumpIfSmi(input, is_not_string); |
2395 | 2380 |
2396 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); | 2381 Condition cond = masm_->IsObjectStringType(input, temp1, temp1); |
2397 | 2382 |
2398 return cond; | 2383 return cond; |
2399 } | 2384 } |
2400 | 2385 |
2401 | 2386 |
2402 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { | 2387 void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { |
2403 Register reg = ToRegister(instr->value()); | 2388 Register reg = ToRegister(instr->value()); |
2404 Register temp = ToRegister(instr->temp()); | 2389 Register temp = ToRegister(instr->temp()); |
2405 | 2390 |
2406 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2391 Condition true_cond = EmitIsString(reg, temp, instr->FalseLabel(chunk_)); |
2407 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2408 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2409 | 2392 |
2410 Condition true_cond = EmitIsString(reg, temp, false_label); | 2393 EmitBranch(instr, true_cond); |
2411 | |
2412 EmitBranch(true_block, false_block, true_cond); | |
2413 } | 2394 } |
2414 | 2395 |
2415 | 2396 |
2416 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 2397 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
2417 Operand input = ToOperand(instr->value()); | 2398 Operand input = ToOperand(instr->value()); |
2418 | 2399 |
2419 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2420 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2421 | |
2422 __ test(input, Immediate(kSmiTagMask)); | 2400 __ test(input, Immediate(kSmiTagMask)); |
2423 EmitBranch(true_block, false_block, zero); | 2401 EmitBranch(instr, zero); |
2424 } | 2402 } |
2425 | 2403 |
2426 | 2404 |
2427 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { | 2405 void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { |
2428 Register input = ToRegister(instr->value()); | 2406 Register input = ToRegister(instr->value()); |
2429 Register temp = ToRegister(instr->temp()); | 2407 Register temp = ToRegister(instr->temp()); |
2430 | 2408 |
2431 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2432 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2433 | |
2434 STATIC_ASSERT(kSmiTag == 0); | 2409 STATIC_ASSERT(kSmiTag == 0); |
2435 __ JumpIfSmi(input, chunk_->GetAssemblyLabel(false_block)); | 2410 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2436 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2411 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
2437 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), | 2412 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), |
2438 1 << Map::kIsUndetectable); | 2413 1 << Map::kIsUndetectable); |
2439 EmitBranch(true_block, false_block, not_zero); | 2414 EmitBranch(instr, not_zero); |
2440 } | 2415 } |
2441 | 2416 |
2442 | 2417 |
2443 static Condition ComputeCompareCondition(Token::Value op) { | 2418 static Condition ComputeCompareCondition(Token::Value op) { |
2444 switch (op) { | 2419 switch (op) { |
2445 case Token::EQ_STRICT: | 2420 case Token::EQ_STRICT: |
2446 case Token::EQ: | 2421 case Token::EQ: |
2447 return equal; | 2422 return equal; |
2448 case Token::LT: | 2423 case Token::LT: |
2449 return less; | 2424 return less; |
2450 case Token::GT: | 2425 case Token::GT: |
2451 return greater; | 2426 return greater; |
2452 case Token::LTE: | 2427 case Token::LTE: |
2453 return less_equal; | 2428 return less_equal; |
2454 case Token::GTE: | 2429 case Token::GTE: |
2455 return greater_equal; | 2430 return greater_equal; |
2456 default: | 2431 default: |
2457 UNREACHABLE(); | 2432 UNREACHABLE(); |
2458 return no_condition; | 2433 return no_condition; |
2459 } | 2434 } |
2460 } | 2435 } |
2461 | 2436 |
2462 | 2437 |
2463 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2438 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2464 Token::Value op = instr->op(); | 2439 Token::Value op = instr->op(); |
2465 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2466 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2467 | 2440 |
2468 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2441 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2469 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2442 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2470 | 2443 |
2471 Condition condition = ComputeCompareCondition(op); | 2444 Condition condition = ComputeCompareCondition(op); |
2472 __ test(eax, Operand(eax)); | 2445 __ test(eax, Operand(eax)); |
2473 | 2446 |
2474 EmitBranch(true_block, false_block, condition); | 2447 EmitBranch(instr, condition); |
2475 } | 2448 } |
2476 | 2449 |
2477 | 2450 |
2478 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2451 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
2479 InstanceType from = instr->from(); | 2452 InstanceType from = instr->from(); |
2480 InstanceType to = instr->to(); | 2453 InstanceType to = instr->to(); |
2481 if (from == FIRST_TYPE) return to; | 2454 if (from == FIRST_TYPE) return to; |
2482 ASSERT(from == to || to == LAST_TYPE); | 2455 ASSERT(from == to || to == LAST_TYPE); |
2483 return from; | 2456 return from; |
2484 } | 2457 } |
2485 | 2458 |
2486 | 2459 |
2487 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { | 2460 static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { |
2488 InstanceType from = instr->from(); | 2461 InstanceType from = instr->from(); |
2489 InstanceType to = instr->to(); | 2462 InstanceType to = instr->to(); |
2490 if (from == to) return equal; | 2463 if (from == to) return equal; |
2491 if (to == LAST_TYPE) return above_equal; | 2464 if (to == LAST_TYPE) return above_equal; |
2492 if (from == FIRST_TYPE) return below_equal; | 2465 if (from == FIRST_TYPE) return below_equal; |
2493 UNREACHABLE(); | 2466 UNREACHABLE(); |
2494 return equal; | 2467 return equal; |
2495 } | 2468 } |
2496 | 2469 |
2497 | 2470 |
2498 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 2471 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
2499 Register input = ToRegister(instr->value()); | 2472 Register input = ToRegister(instr->value()); |
2500 Register temp = ToRegister(instr->temp()); | 2473 Register temp = ToRegister(instr->temp()); |
2501 | 2474 |
2502 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2475 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
2503 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2504 | |
2505 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2506 | |
2507 __ JumpIfSmi(input, false_label); | |
2508 | 2476 |
2509 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); | 2477 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
2510 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); | 2478 EmitBranch(instr, BranchCondition(instr->hydrogen())); |
2511 } | 2479 } |
2512 | 2480 |
2513 | 2481 |
2514 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { | 2482 void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) { |
2515 Register input = ToRegister(instr->value()); | 2483 Register input = ToRegister(instr->value()); |
2516 Register result = ToRegister(instr->result()); | 2484 Register result = ToRegister(instr->result()); |
2517 | 2485 |
2518 __ AssertString(input); | 2486 __ AssertString(input); |
2519 | 2487 |
2520 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); | 2488 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); |
2521 __ IndexFromHash(result, result); | 2489 __ IndexFromHash(result, result); |
2522 } | 2490 } |
2523 | 2491 |
2524 | 2492 |
2525 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 2493 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
2526 LHasCachedArrayIndexAndBranch* instr) { | 2494 LHasCachedArrayIndexAndBranch* instr) { |
2527 Register input = ToRegister(instr->value()); | 2495 Register input = ToRegister(instr->value()); |
2528 | 2496 |
2529 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
2530 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
2531 | |
2532 __ test(FieldOperand(input, String::kHashFieldOffset), | 2497 __ test(FieldOperand(input, String::kHashFieldOffset), |
2533 Immediate(String::kContainsCachedArrayIndexMask)); | 2498 Immediate(String::kContainsCachedArrayIndexMask)); |
2534 EmitBranch(true_block, false_block, equal); | 2499 EmitBranch(instr, equal); |
2535 } | 2500 } |
2536 | 2501 |
2537 | 2502 |
2538 // Branches to a label or falls through with the answer in the z flag. Trashes | 2503 // Branches to a label or falls through with the answer in the z flag. Trashes |
2539 // the temp registers, but not the input. | 2504 // the temp registers, but not the input. |
2540 void LCodeGen::EmitClassOfTest(Label* is_true, | 2505 void LCodeGen::EmitClassOfTest(Label* is_true, |
2541 Label* is_false, | 2506 Label* is_false, |
2542 Handle<String>class_name, | 2507 Handle<String>class_name, |
2543 Register input, | 2508 Register input, |
2544 Register temp, | 2509 Register temp, |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2600 } | 2565 } |
2601 | 2566 |
2602 | 2567 |
2603 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 2568 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
2604 Register input = ToRegister(instr->value()); | 2569 Register input = ToRegister(instr->value()); |
2605 Register temp = ToRegister(instr->temp()); | 2570 Register temp = ToRegister(instr->temp()); |
2606 Register temp2 = ToRegister(instr->temp2()); | 2571 Register temp2 = ToRegister(instr->temp2()); |
2607 | 2572 |
2608 Handle<String> class_name = instr->hydrogen()->class_name(); | 2573 Handle<String> class_name = instr->hydrogen()->class_name(); |
2609 | 2574 |
2610 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2575 EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
2611 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2576 class_name, input, temp, temp2); |
2612 | 2577 |
2613 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 2578 EmitBranch(instr, equal); |
2614 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
2615 | |
2616 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | |
2617 | |
2618 EmitBranch(true_block, false_block, equal); | |
2619 } | 2579 } |
2620 | 2580 |
2621 | 2581 |
2622 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2582 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
2623 Register reg = ToRegister(instr->value()); | 2583 Register reg = ToRegister(instr->value()); |
2624 int true_block = instr->true_block_id(); | |
2625 int false_block = instr->false_block_id(); | |
2626 | |
2627 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2584 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
2628 EmitBranch(true_block, false_block, equal); | 2585 EmitBranch(instr, equal); |
2629 } | 2586 } |
2630 | 2587 |
2631 | 2588 |
2632 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2589 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2633 // Object and function are in fixed registers defined by the stub. | 2590 // Object and function are in fixed registers defined by the stub. |
2634 ASSERT(ToRegister(instr->context()).is(esi)); | 2591 ASSERT(ToRegister(instr->context()).is(esi)); |
2635 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2592 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
2636 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2593 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
2637 | 2594 |
2638 Label true_value, done; | 2595 Label true_value, done; |
(...skipping 3597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6236 | 6193 |
6237 void LCodeGen::DoTypeof(LTypeof* instr) { | 6194 void LCodeGen::DoTypeof(LTypeof* instr) { |
6238 LOperand* input = instr->value(); | 6195 LOperand* input = instr->value(); |
6239 EmitPushTaggedOperand(input); | 6196 EmitPushTaggedOperand(input); |
6240 CallRuntime(Runtime::kTypeof, 1, instr); | 6197 CallRuntime(Runtime::kTypeof, 1, instr); |
6241 } | 6198 } |
6242 | 6199 |
6243 | 6200 |
6244 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 6201 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
6245 Register input = ToRegister(instr->value()); | 6202 Register input = ToRegister(instr->value()); |
6246 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
6247 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
6248 Label* true_label = chunk_->GetAssemblyLabel(true_block); | |
6249 Label* false_label = chunk_->GetAssemblyLabel(false_block); | |
6250 | 6203 |
6251 Condition final_branch_condition = | 6204 Condition final_branch_condition = |
6252 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); | 6205 EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 6206 input, instr->type_literal()); |
6253 if (final_branch_condition != no_condition) { | 6207 if (final_branch_condition != no_condition) { |
6254 EmitBranch(true_block, false_block, final_branch_condition); | 6208 EmitBranch(instr, final_branch_condition); |
6255 } | 6209 } |
6256 } | 6210 } |
6257 | 6211 |
6258 | 6212 |
6259 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 6213 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
6260 Label* false_label, | 6214 Label* false_label, |
6261 Register input, | 6215 Register input, |
6262 Handle<String> type_name) { | 6216 Handle<String> type_name) { |
6263 Condition final_branch_condition = no_condition; | 6217 Condition final_branch_condition = no_condition; |
6264 if (type_name->Equals(heap()->number_string())) { | 6218 if (type_name->Equals(heap()->number_string())) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6325 | 6279 |
6326 } else { | 6280 } else { |
6327 __ jmp(false_label); | 6281 __ jmp(false_label); |
6328 } | 6282 } |
6329 return final_branch_condition; | 6283 return final_branch_condition; |
6330 } | 6284 } |
6331 | 6285 |
6332 | 6286 |
6333 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 6287 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
6334 Register temp = ToRegister(instr->temp()); | 6288 Register temp = ToRegister(instr->temp()); |
6335 int true_block = chunk_->LookupDestination(instr->true_block_id()); | |
6336 int false_block = chunk_->LookupDestination(instr->false_block_id()); | |
6337 | 6289 |
6338 EmitIsConstructCall(temp); | 6290 EmitIsConstructCall(temp); |
6339 EmitBranch(true_block, false_block, equal); | 6291 EmitBranch(instr, equal); |
6340 } | 6292 } |
6341 | 6293 |
6342 | 6294 |
6343 void LCodeGen::EmitIsConstructCall(Register temp) { | 6295 void LCodeGen::EmitIsConstructCall(Register temp) { |
6344 // Get the frame pointer for the calling frame. | 6296 // Get the frame pointer for the calling frame. |
6345 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 6297 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
6346 | 6298 |
6347 // Skip the arguments adaptor frame if it exists. | 6299 // Skip the arguments adaptor frame if it exists. |
6348 Label check_frame_marker; | 6300 Label check_frame_marker; |
6349 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), | 6301 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6593 FixedArray::kHeaderSize - kPointerSize)); | 6545 FixedArray::kHeaderSize - kPointerSize)); |
6594 __ bind(&done); | 6546 __ bind(&done); |
6595 } | 6547 } |
6596 | 6548 |
6597 | 6549 |
6598 #undef __ | 6550 #undef __ |
6599 | 6551 |
6600 } } // namespace v8::internal | 6552 } } // namespace v8::internal |
6601 | 6553 |
6602 #endif // V8_TARGET_ARCH_IA32 | 6554 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |