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