OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 #include "src/ic/handler-configuration.h" | 8 #include "src/ic/handler-configuration.h" |
9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
10 | 10 |
(...skipping 2258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2269 if (FLAG_allocation_site_pretenuring) { | 2269 if (FLAG_allocation_site_pretenuring) { |
2270 Node* count = LoadObjectField(allocation_site, | 2270 Node* count = LoadObjectField(allocation_site, |
2271 AllocationSite::kPretenureCreateCountOffset); | 2271 AllocationSite::kPretenureCreateCountOffset); |
2272 Node* incremented_count = SmiAdd(count, SmiConstant(Smi::FromInt(1))); | 2272 Node* incremented_count = SmiAdd(count, SmiConstant(Smi::FromInt(1))); |
2273 StoreObjectFieldNoWriteBarrier(allocation_site, | 2273 StoreObjectFieldNoWriteBarrier(allocation_site, |
2274 AllocationSite::kPretenureCreateCountOffset, | 2274 AllocationSite::kPretenureCreateCountOffset, |
2275 incremented_count); | 2275 incremented_count); |
2276 } | 2276 } |
2277 } | 2277 } |
2278 | 2278 |
2279 Node* CodeStubAssembler::TruncateNumberToFloat64(Node* value, | |
Benedikt Meurer
2016/11/11 10:25:35
This name is confusing as the function doesn't tru
jgruber
2016/11/11 10:57:40
Done.
| |
2280 Label* if_valueisnotnumber) { | |
2281 Label out(this); | |
2282 Variable var_result(this, MachineRepresentation::kFloat64); | |
2283 var_result.Bind(Float64Constant(0.0)); | |
2284 | |
2285 // Check if the {value} is a Smi or a HeapObject. | |
2286 Label if_valueissmi(this), if_valueisnotsmi(this); | |
2287 Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); | |
2288 | |
2289 Bind(&if_valueissmi); | |
2290 { | |
2291 // Convert the Smi {value}. | |
2292 var_result.Bind(SmiToFloat64(value)); | |
2293 Goto(&out); | |
2294 } | |
2295 | |
2296 Bind(&if_valueisnotsmi); | |
2297 { | |
2298 // Check if {value} is a HeapNumber. | |
2299 Label if_valueisheapnumber(this); | |
2300 Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()), | |
2301 &if_valueisheapnumber, if_valueisnotnumber); | |
2302 | |
2303 Bind(&if_valueisheapnumber); | |
2304 { | |
2305 // Load the floating point value. | |
2306 var_result.Bind(LoadHeapNumberValue(value)); | |
2307 Goto(&out); | |
2308 } | |
2309 } | |
2310 Bind(&out); | |
2311 return var_result.value(); | |
2312 } | |
2313 | |
2279 Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { | 2314 Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) { |
2280 // We might need to loop once due to ToNumber conversion. | 2315 // We might need to loop once due to ToNumber conversion. |
2281 Variable var_value(this, MachineRepresentation::kTagged), | 2316 Variable var_value(this, MachineRepresentation::kTagged), |
2282 var_result(this, MachineRepresentation::kFloat64); | 2317 var_result(this, MachineRepresentation::kFloat64); |
2283 Label loop(this, &var_value), done_loop(this, &var_result); | 2318 Label loop(this, &var_value), done_loop(this, &var_result); |
2284 var_value.Bind(value); | 2319 var_value.Bind(value); |
2285 Goto(&loop); | 2320 Goto(&loop); |
2286 Bind(&loop); | 2321 Bind(&loop); |
2287 { | 2322 { |
2323 Label if_valueisnotheapnumber(this, Label::kDeferred); | |
2324 | |
2288 // Load the current {value}. | 2325 // Load the current {value}. |
2289 value = var_value.value(); | 2326 value = var_value.value(); |
2290 | 2327 |
2291 // Check if the {value} is a Smi or a HeapObject. | 2328 // Convert {value} to Float64 if it is a number and convert it to a number |
2292 Label if_valueissmi(this), if_valueisnotsmi(this); | 2329 // otherwise. |
2293 Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi); | 2330 Node* const result = |
2331 TruncateNumberToFloat64(value, &if_valueisnotheapnumber); | |
2332 var_result.Bind(result); | |
2333 Goto(&done_loop); | |
2294 | 2334 |
2295 Bind(&if_valueissmi); | 2335 Bind(&if_valueisnotheapnumber); |
2296 { | 2336 { |
2297 // Convert the Smi {value}. | 2337 // Convert the {value} to a Number first. |
2298 var_result.Bind(SmiToFloat64(value)); | 2338 Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
2299 Goto(&done_loop); | 2339 var_value.Bind(CallStub(callable, context, value)); |
2300 } | 2340 Goto(&loop); |
2301 | |
2302 Bind(&if_valueisnotsmi); | |
2303 { | |
2304 // Check if {value} is a HeapNumber. | |
2305 Label if_valueisheapnumber(this), | |
2306 if_valueisnotheapnumber(this, Label::kDeferred); | |
2307 Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()), | |
2308 &if_valueisheapnumber, &if_valueisnotheapnumber); | |
2309 | |
2310 Bind(&if_valueisheapnumber); | |
2311 { | |
2312 // Load the floating point value. | |
2313 var_result.Bind(LoadHeapNumberValue(value)); | |
2314 Goto(&done_loop); | |
2315 } | |
2316 | |
2317 Bind(&if_valueisnotheapnumber); | |
2318 { | |
2319 // Convert the {value} to a Number first. | |
2320 Callable callable = CodeFactory::NonNumberToNumber(isolate()); | |
2321 var_value.Bind(CallStub(callable, context, value)); | |
2322 Goto(&loop); | |
2323 } | |
2324 } | 2341 } |
2325 } | 2342 } |
2326 Bind(&done_loop); | 2343 Bind(&done_loop); |
2327 return var_result.value(); | 2344 return var_result.value(); |
2328 } | 2345 } |
2329 | 2346 |
2330 Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { | 2347 Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) { |
2331 // We might need to loop once due to ToNumber conversion. | 2348 // We might need to loop once due to ToNumber conversion. |
2332 Variable var_value(this, MachineRepresentation::kTagged), | 2349 Variable var_value(this, MachineRepresentation::kTagged), |
2333 var_result(this, MachineRepresentation::kWord32); | 2350 var_result(this, MachineRepresentation::kWord32); |
(...skipping 6068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8402 Bind(&if_notequal); | 8419 Bind(&if_notequal); |
8403 { | 8420 { |
8404 result.Bind(BooleanConstant(mode == kNegateResult)); | 8421 result.Bind(BooleanConstant(mode == kNegateResult)); |
8405 Goto(&end); | 8422 Goto(&end); |
8406 } | 8423 } |
8407 | 8424 |
8408 Bind(&end); | 8425 Bind(&end); |
8409 return result.value(); | 8426 return result.value(); |
8410 } | 8427 } |
8411 | 8428 |
8429 // ECMA#sec-samevalue | |
8430 // This algorithm differs from the Strict Equality Comparison Algorithm in its | |
8431 // treatment of signed zeroes and NaNs. | |
8432 compiler::Node* CodeStubAssembler::SameValue(compiler::Node* lhs, | |
8433 compiler::Node* rhs, | |
8434 compiler::Node* context) { | |
8435 Variable var_result(this, MachineType::PointerRepresentation()); | |
8436 Label strict_equal(this), out(this); | |
8437 | |
8438 Node* const int_false = IntPtrConstant(0); | |
8439 Node* const int_true = IntPtrConstant(1); | |
8440 | |
8441 Label if_equal(this), if_notequal(this); | |
8442 Branch(WordEqual(lhs, rhs), &if_equal, &if_notequal); | |
8443 | |
8444 Bind(&if_equal); | |
8445 { | |
8446 // This covers the case when {lhs} == {rhs}. We can simply return true | |
8447 // because SameValue considers two NaNs to be equal. | |
8448 | |
8449 var_result.Bind(int_true); | |
8450 Goto(&out); | |
8451 } | |
8452 | |
8453 Bind(&if_notequal); | |
8454 { | |
8455 // This covers the case when {lhs} != {rhs}. We only handle numbers here | |
8456 // and defer to StrictEqual for the rest. | |
8457 | |
8458 Node* const lhs_float = TruncateNumberToFloat64(lhs, &strict_equal); | |
Benedikt Meurer
2016/11/11 10:25:35
Truncate is highly confusing here, since you don't
jgruber
2016/11/11 10:57:40
Done.
| |
8459 Node* const rhs_float = TruncateNumberToFloat64(rhs, &strict_equal); | |
8460 | |
8461 Label if_lhsisnan(this), if_lhsnotnan(this); | |
8462 BranchIfFloat64IsNaN(lhs_float, &if_lhsisnan, &if_lhsnotnan); | |
8463 | |
8464 Bind(&if_lhsisnan); | |
8465 { | |
8466 // Return true iff {rhs} is NaN. | |
8467 | |
8468 Node* const result = | |
8469 Select(Float64Equal(rhs_float, rhs_float), int_false, int_true); | |
8470 var_result.Bind(result); | |
8471 Goto(&out); | |
8472 } | |
8473 | |
8474 Bind(&if_lhsnotnan); | |
8475 { | |
8476 Label if_floatisequal(this), if_floatnotequal(this); | |
8477 Branch(Float64Equal(lhs_float, rhs_float), &if_floatisequal, | |
8478 &if_floatnotequal); | |
8479 | |
8480 Bind(&if_floatisequal); | |
8481 { | |
8482 // We still need to handle the case when {lhs} and {rhs} are -0.0 and | |
8483 // 0.0 (or vice versa). Compare the high word to | |
8484 // distinguish between the two. | |
8485 | |
8486 Node* const lhs_hi_word = Float64ExtractHighWord32(lhs_float); | |
8487 Node* const rhs_hi_word = Float64ExtractHighWord32(rhs_float); | |
8488 | |
8489 // If x is +0 and y is -0, return false. | |
8490 // If x is -0 and y is +0, return false. | |
8491 | |
8492 Node* const result = Word32Equal(lhs_hi_word, rhs_hi_word); | |
8493 var_result.Bind(result); | |
8494 Goto(&out); | |
8495 } | |
8496 | |
8497 Bind(&if_floatnotequal); | |
8498 { | |
8499 var_result.Bind(int_false); | |
8500 Goto(&out); | |
8501 } | |
8502 } | |
8503 } | |
8504 | |
8505 Bind(&strict_equal); | |
8506 { | |
8507 Node* const is_equal = StrictEqual(kDontNegateResult, lhs, rhs, context); | |
8508 Node* const result = WordEqual(is_equal, TrueConstant()); | |
8509 var_result.Bind(result); | |
8510 Goto(&out); | |
8511 } | |
8512 | |
8513 Bind(&out); | |
8514 return var_result.value(); | |
8515 } | |
8516 | |
8412 compiler::Node* CodeStubAssembler::ForInFilter(compiler::Node* key, | 8517 compiler::Node* CodeStubAssembler::ForInFilter(compiler::Node* key, |
8413 compiler::Node* object, | 8518 compiler::Node* object, |
8414 compiler::Node* context) { | 8519 compiler::Node* context) { |
8415 Label return_undefined(this, Label::kDeferred), return_to_name(this), | 8520 Label return_undefined(this, Label::kDeferred), return_to_name(this), |
8416 end(this); | 8521 end(this); |
8417 | 8522 |
8418 Variable var_result(this, MachineRepresentation::kTagged); | 8523 Variable var_result(this, MachineRepresentation::kTagged); |
8419 | 8524 |
8420 Node* has_property = | 8525 Node* has_property = |
8421 HasProperty(object, key, context, Runtime::kForInHasProperty); | 8526 HasProperty(object, key, context, Runtime::kForInHasProperty); |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8910 } | 9015 } |
8911 | 9016 |
8912 void CodeStubArguments::PopAndReturn(compiler::Node* value) { | 9017 void CodeStubArguments::PopAndReturn(compiler::Node* value) { |
8913 assembler_->PopAndReturn( | 9018 assembler_->PopAndReturn( |
8914 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)), | 9019 assembler_->IntPtrAddFoldConstants(argc_, assembler_->IntPtrConstant(1)), |
8915 value); | 9020 value); |
8916 } | 9021 } |
8917 | 9022 |
8918 } // namespace internal | 9023 } // namespace internal |
8919 } // namespace v8 | 9024 } // namespace v8 |
OLD | NEW |