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 | 4 |
5 #include "src/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
8 #include "src/frames.h" | 8 #include "src/frames.h" |
9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
(...skipping 2342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2353 Bind(&runtime); | 2353 Bind(&runtime); |
2354 { | 2354 { |
2355 var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input)); | 2355 var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input)); |
2356 Goto(&end); | 2356 Goto(&end); |
2357 } | 2357 } |
2358 | 2358 |
2359 Bind(&end); | 2359 Bind(&end); |
2360 return var_result.value(); | 2360 return var_result.value(); |
2361 } | 2361 } |
2362 | 2362 |
2363 Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { | |
2364 // Assert input is a HeapObject (not smi or heap number) | |
2365 Assert(Word32BinaryNot(WordIsSmi(input))); | |
2366 Assert( | |
2367 Word32NotEqual(LoadInstanceType(input), Int32Constant(HEAP_NUMBER_TYPE))); | |
Igor Sheludko
2016/09/09 11:33:15
How about doing a map check here?
| |
2368 | |
2369 // We might need to loop once here due to ToPrimitive conversions. | |
2370 Variable var_input(this, MachineRepresentation::kTagged); | |
2371 Variable var_result(this, MachineRepresentation::kTagged); | |
2372 Label loop(this, &var_input); | |
2373 Label end(this); | |
2374 var_input.Bind(input); | |
2375 Goto(&loop); | |
2376 Bind(&loop); | |
2377 { | |
2378 // Load the current {input} value (known to be a HeapObject). | |
2379 Node* input = var_input.value(); | |
2380 | |
2381 // Dispatch on the {input} instance type. | |
2382 Node* input_instance_type = LoadInstanceType(input); | |
2383 Label if_inputisstring(this), if_inputisoddball(this), | |
2384 if_inputisreceiver(this, Label::kDeferred), | |
2385 if_inputisother(this, Label::kDeferred); | |
2386 GotoIf( | |
2387 Int32LessThan(input_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), | |
2388 &if_inputisstring); | |
2389 GotoIf(Word32Equal(input_instance_type, Int32Constant(ODDBALL_TYPE)), | |
2390 &if_inputisoddball); | |
2391 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
2392 Branch(Int32GreaterThanOrEqual(input_instance_type, | |
2393 Int32Constant(FIRST_JS_RECEIVER_TYPE)), | |
2394 &if_inputisreceiver, &if_inputisother); | |
2395 | |
2396 Bind(&if_inputisstring); | |
2397 { | |
2398 // The {input} is a String, use the fast stub to convert it to a Number. | |
2399 var_result.Bind(StringToNumber(context, input)); | |
2400 Goto(&end); | |
2401 } | |
2402 | |
2403 Bind(&if_inputisoddball); | |
2404 { | |
2405 // The {input} is an Oddball, we just need to load the Number value of it. | |
2406 var_result.Bind(LoadObjectField(input, Oddball::kToNumberOffset)); | |
2407 Goto(&end); | |
2408 } | |
2409 | |
2410 Bind(&if_inputisreceiver); | |
2411 { | |
2412 // The {input} is a JSReceiver, we need to convert it to a Primitive first | |
2413 // using the ToPrimitive type conversion, preferably yielding a Number. | |
2414 Callable callable = CodeFactory::NonPrimitiveToPrimitive( | |
2415 isolate(), ToPrimitiveHint::kNumber); | |
2416 Node* result = CallStub(callable, context, input); | |
2417 | |
2418 // Check if the {result} is already a Number. | |
2419 Label if_resultisnumber(this), if_resultisnotnumber(this); | |
2420 GotoIf(WordIsSmi(result), &if_resultisnumber); | |
2421 Node* result_map = LoadMap(result); | |
2422 Branch(WordEqual(result_map, HeapNumberMapConstant()), &if_resultisnumber, | |
2423 &if_resultisnotnumber); | |
2424 | |
2425 Bind(&if_resultisnumber); | |
2426 { | |
2427 // The ToPrimitive conversion already gave us a Number, so we're done. | |
2428 var_result.Bind(result); | |
2429 Goto(&end); | |
2430 } | |
2431 | |
2432 Bind(&if_resultisnotnumber); | |
2433 { | |
2434 // We now have a Primitive {result}, but it's not yet a Number. | |
2435 var_input.Bind(result); | |
2436 Goto(&loop); | |
2437 } | |
2438 } | |
2439 | |
2440 Bind(&if_inputisother); | |
2441 { | |
2442 // The {input} is something else (i.e. Symbol or Simd128Value), let the | |
2443 // runtime figure out the correct exception. | |
2444 // Note: We cannot tail call to the runtime here, as js-to-wasm | |
2445 // trampolines also use this code currently, and they declare all | |
2446 // outgoing parameters as untagged, while we would push a tagged | |
2447 // object here. | |
2448 var_result.Bind(CallRuntime(Runtime::kToNumber, context, input)); | |
2449 Goto(&end); | |
2450 } | |
2451 } | |
2452 | |
2453 Bind(&end); | |
2454 return var_result.value(); | |
2455 } | |
2456 | |
2457 Node* CodeStubAssembler::ToNumber(Node* context, Node* input) { | |
2458 Variable var_result(this, MachineRepresentation::kTagged); | |
2459 Label end(this); | |
2460 | |
2461 Label not_smi(this, Label::kDeferred); | |
2462 GotoUnless(WordIsSmi(input), ¬_smi); | |
2463 var_result.Bind(input); | |
2464 Goto(&end); | |
2465 | |
2466 Bind(¬_smi); | |
2467 { | |
2468 Label not_heap_number(this, Label::kDeferred); | |
2469 Node* input_instance_type = LoadInstanceType(input); | |
2470 GotoIf(Word32NotEqual(input_instance_type, Int32Constant(HEAP_NUMBER_TYPE)), | |
Igor Sheludko
2016/09/09 11:33:15
While we are here, how about doing a map check ins
| |
2471 ¬_heap_number); | |
2472 | |
2473 var_result.Bind(input); | |
2474 Goto(&end); | |
2475 | |
2476 Bind(¬_heap_number); | |
2477 { | |
2478 var_result.Bind(NonNumberToNumber(context, input)); | |
2479 Goto(&end); | |
2480 } | |
2481 } | |
2482 | |
2483 Bind(&end); | |
2484 return var_result.value(); | |
2485 } | |
2486 | |
2363 Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, | 2487 Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, |
2364 uint32_t mask) { | 2488 uint32_t mask) { |
2365 return Word32Shr(Word32And(word32, Int32Constant(mask)), | 2489 return Word32Shr(Word32And(word32, Int32Constant(mask)), |
2366 static_cast<int>(shift)); | 2490 static_cast<int>(shift)); |
2367 } | 2491 } |
2368 | 2492 |
2369 void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) { | 2493 void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) { |
2370 if (FLAG_native_code_counters && counter->Enabled()) { | 2494 if (FLAG_native_code_counters && counter->Enabled()) { |
2371 Node* counter_address = ExternalConstant(ExternalReference(counter)); | 2495 Node* counter_address = ExternalConstant(ExternalReference(counter)); |
2372 StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, | 2496 StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, |
(...skipping 1948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4321 Heap::kTheHoleValueRootIndex); | 4445 Heap::kTheHoleValueRootIndex); |
4322 | 4446 |
4323 // Store the WeakCell in the feedback vector. | 4447 // Store the WeakCell in the feedback vector. |
4324 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 4448 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
4325 CodeStubAssembler::SMI_PARAMETERS); | 4449 CodeStubAssembler::SMI_PARAMETERS); |
4326 return cell; | 4450 return cell; |
4327 } | 4451 } |
4328 | 4452 |
4329 } // namespace internal | 4453 } // namespace internal |
4330 } // namespace v8 | 4454 } // namespace v8 |
OLD | NEW |