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/builtins/builtins.h" | 5 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 Label return_true(assembler), return_false(assembler); | 312 Label return_true(assembler), return_false(assembler); |
313 assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false); | 313 assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false); |
314 | 314 |
315 assembler->Bind(&return_true); | 315 assembler->Bind(&return_true); |
316 assembler->Return(assembler->BooleanConstant(true)); | 316 assembler->Return(assembler->BooleanConstant(true)); |
317 | 317 |
318 assembler->Bind(&return_false); | 318 assembler->Bind(&return_false); |
319 assembler->Return(assembler->BooleanConstant(false)); | 319 assembler->Return(assembler->BooleanConstant(false)); |
320 } | 320 } |
321 | 321 |
| 322 void Builtins::Generate_ToLength(CodeStubAssembler* assembler) { |
| 323 typedef CodeStubAssembler::Label Label; |
| 324 typedef compiler::Node Node; |
| 325 typedef CodeStubAssembler::Variable Variable; |
| 326 |
| 327 Node* context = assembler->Parameter(1); |
| 328 |
| 329 // We might need to loop once for ToNumber conversion. |
| 330 Variable var_len(assembler, MachineRepresentation::kTagged); |
| 331 Label loop(assembler, &var_len); |
| 332 var_len.Bind(assembler->Parameter(0)); |
| 333 assembler->Goto(&loop); |
| 334 assembler->Bind(&loop); |
| 335 { |
| 336 // Shared entry points. |
| 337 Label return_len(assembler), |
| 338 return_two53minus1(assembler, Label::kDeferred), |
| 339 return_zero(assembler, Label::kDeferred); |
| 340 |
| 341 // Load the current {len} value. |
| 342 Node* len = var_len.value(); |
| 343 |
| 344 // Check if {len} is a positive Smi. |
| 345 assembler->GotoIf(assembler->WordIsPositiveSmi(len), &return_len); |
| 346 |
| 347 // Check if {len} is a (negative) Smi. |
| 348 assembler->GotoIf(assembler->WordIsSmi(len), &return_zero); |
| 349 |
| 350 // Check if {len} is a HeapNumber. |
| 351 Label if_lenisheapnumber(assembler), |
| 352 if_lenisnotheapnumber(assembler, Label::kDeferred); |
| 353 assembler->Branch(assembler->IsHeapNumberMap(assembler->LoadMap(len)), |
| 354 &if_lenisheapnumber, &if_lenisnotheapnumber); |
| 355 |
| 356 assembler->Bind(&if_lenisheapnumber); |
| 357 { |
| 358 // Load the floating-point value of {len}. |
| 359 Node* len_value = assembler->LoadHeapNumberValue(len); |
| 360 |
| 361 // Check if {len} is not greater than zero. |
| 362 assembler->GotoUnless(assembler->Float64GreaterThan( |
| 363 len_value, assembler->Float64Constant(0.0)), |
| 364 &return_zero); |
| 365 |
| 366 // Check if {len} is greater than or equal to 2^53-1. |
| 367 assembler->GotoIf( |
| 368 assembler->Float64GreaterThanOrEqual( |
| 369 len_value, assembler->Float64Constant(kMaxSafeInteger)), |
| 370 &return_two53minus1); |
| 371 |
| 372 // Round the {len} towards -Infinity. |
| 373 Node* value = assembler->Float64Floor(len_value); |
| 374 Node* result = assembler->ChangeFloat64ToTagged(value); |
| 375 assembler->Return(result); |
| 376 } |
| 377 |
| 378 assembler->Bind(&if_lenisnotheapnumber); |
| 379 { |
| 380 // Need to convert {len} to a Number first. |
| 381 Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate()); |
| 382 var_len.Bind(assembler->CallStub(callable, context, len)); |
| 383 assembler->Goto(&loop); |
| 384 } |
| 385 |
| 386 assembler->Bind(&return_len); |
| 387 assembler->Return(var_len.value()); |
| 388 |
| 389 assembler->Bind(&return_two53minus1); |
| 390 assembler->Return(assembler->NumberConstant(kMaxSafeInteger)); |
| 391 |
| 392 assembler->Bind(&return_zero); |
| 393 assembler->Return(assembler->SmiConstant(Smi::FromInt(0))); |
| 394 } |
| 395 } |
| 396 |
| 397 void Builtins::Generate_ToInteger(CodeStubAssembler* assembler) { |
| 398 typedef TypeConversionDescriptor Descriptor; |
| 399 |
| 400 compiler::Node* input = assembler->Parameter(Descriptor::kArgument); |
| 401 compiler::Node* context = assembler->Parameter(Descriptor::kContext); |
| 402 |
| 403 assembler->Return(assembler->ToInteger(context, input)); |
| 404 } |
| 405 |
| 406 // ES6 section 7.1.13 ToObject (argument) |
| 407 void Builtins::Generate_ToObject(CodeStubAssembler* assembler) { |
| 408 typedef compiler::Node Node; |
| 409 typedef CodeStubAssembler::Label Label; |
| 410 typedef CodeStubAssembler::Variable Variable; |
| 411 typedef TypeConversionDescriptor Descriptor; |
| 412 |
| 413 Label if_number(assembler, Label::kDeferred), if_notsmi(assembler), |
| 414 if_jsreceiver(assembler), if_noconstructor(assembler, Label::kDeferred), |
| 415 if_wrapjsvalue(assembler); |
| 416 |
| 417 Node* object = assembler->Parameter(Descriptor::kArgument); |
| 418 Node* context = assembler->Parameter(Descriptor::kContext); |
| 419 |
| 420 Variable constructor_function_index_var(assembler, |
| 421 MachineType::PointerRepresentation()); |
| 422 |
| 423 assembler->Branch(assembler->WordIsSmi(object), &if_number, &if_notsmi); |
| 424 |
| 425 assembler->Bind(&if_notsmi); |
| 426 Node* map = assembler->LoadMap(object); |
| 427 |
| 428 assembler->GotoIf(assembler->IsHeapNumberMap(map), &if_number); |
| 429 |
| 430 Node* instance_type = assembler->LoadMapInstanceType(map); |
| 431 assembler->GotoIf(assembler->IsJSReceiverInstanceType(instance_type), |
| 432 &if_jsreceiver); |
| 433 |
| 434 Node* constructor_function_index = |
| 435 assembler->LoadMapConstructorFunctionIndex(map); |
| 436 assembler->GotoIf(assembler->WordEqual(constructor_function_index, |
| 437 assembler->IntPtrConstant( |
| 438 Map::kNoConstructorFunctionIndex)), |
| 439 &if_noconstructor); |
| 440 constructor_function_index_var.Bind(constructor_function_index); |
| 441 assembler->Goto(&if_wrapjsvalue); |
| 442 |
| 443 assembler->Bind(&if_number); |
| 444 constructor_function_index_var.Bind( |
| 445 assembler->IntPtrConstant(Context::NUMBER_FUNCTION_INDEX)); |
| 446 assembler->Goto(&if_wrapjsvalue); |
| 447 |
| 448 assembler->Bind(&if_wrapjsvalue); |
| 449 Node* native_context = assembler->LoadNativeContext(context); |
| 450 Node* constructor = assembler->LoadFixedArrayElement( |
| 451 native_context, constructor_function_index_var.value(), 0, |
| 452 CodeStubAssembler::INTPTR_PARAMETERS); |
| 453 Node* initial_map = assembler->LoadObjectField( |
| 454 constructor, JSFunction::kPrototypeOrInitialMapOffset); |
| 455 Node* js_value = assembler->Allocate(JSValue::kSize); |
| 456 assembler->StoreMapNoWriteBarrier(js_value, initial_map); |
| 457 assembler->StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset, |
| 458 Heap::kEmptyFixedArrayRootIndex); |
| 459 assembler->StoreObjectFieldRoot(js_value, JSObject::kElementsOffset, |
| 460 Heap::kEmptyFixedArrayRootIndex); |
| 461 assembler->StoreObjectField(js_value, JSValue::kValueOffset, object); |
| 462 assembler->Return(js_value); |
| 463 |
| 464 assembler->Bind(&if_noconstructor); |
| 465 assembler->TailCallRuntime( |
| 466 Runtime::kThrowUndefinedOrNullToObject, context, |
| 467 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( |
| 468 "ToObject", TENURED))); |
| 469 |
| 470 assembler->Bind(&if_jsreceiver); |
| 471 assembler->Return(object); |
| 472 } |
| 473 |
| 474 // ES6 section 12.5.5 typeof operator |
| 475 void Builtins::Generate_Typeof(CodeStubAssembler* assembler) { |
| 476 typedef compiler::Node Node; |
| 477 typedef TypeofDescriptor Descriptor; |
| 478 |
| 479 Node* object = assembler->Parameter(Descriptor::kObject); |
| 480 Node* context = assembler->Parameter(Descriptor::kContext); |
| 481 |
| 482 assembler->Return(assembler->Typeof(object, context)); |
| 483 } |
| 484 |
322 } // namespace internal | 485 } // namespace internal |
323 } // namespace v8 | 486 } // namespace v8 |
OLD | NEW |