| Index: src/builtins/builtins-conversion.cc
|
| diff --git a/src/builtins/builtins-conversion.cc b/src/builtins/builtins-conversion.cc
|
| index 7fbe4f859e64b05903f9ab93e43bfced543b3d41..a085b149a3fe085b99631f50e066ace59a65d4bf 100644
|
| --- a/src/builtins/builtins-conversion.cc
|
| +++ b/src/builtins/builtins-conversion.cc
|
| @@ -319,5 +319,168 @@ void Builtins::Generate_ToBoolean(CodeStubAssembler* assembler) {
|
| assembler->Return(assembler->BooleanConstant(false));
|
| }
|
|
|
| +void Builtins::Generate_ToLength(CodeStubAssembler* assembler) {
|
| + typedef CodeStubAssembler::Label Label;
|
| + typedef compiler::Node Node;
|
| + typedef CodeStubAssembler::Variable Variable;
|
| +
|
| + Node* context = assembler->Parameter(1);
|
| +
|
| + // We might need to loop once for ToNumber conversion.
|
| + Variable var_len(assembler, MachineRepresentation::kTagged);
|
| + Label loop(assembler, &var_len);
|
| + var_len.Bind(assembler->Parameter(0));
|
| + assembler->Goto(&loop);
|
| + assembler->Bind(&loop);
|
| + {
|
| + // Shared entry points.
|
| + Label return_len(assembler),
|
| + return_two53minus1(assembler, Label::kDeferred),
|
| + return_zero(assembler, Label::kDeferred);
|
| +
|
| + // Load the current {len} value.
|
| + Node* len = var_len.value();
|
| +
|
| + // Check if {len} is a positive Smi.
|
| + assembler->GotoIf(assembler->WordIsPositiveSmi(len), &return_len);
|
| +
|
| + // Check if {len} is a (negative) Smi.
|
| + assembler->GotoIf(assembler->WordIsSmi(len), &return_zero);
|
| +
|
| + // Check if {len} is a HeapNumber.
|
| + Label if_lenisheapnumber(assembler),
|
| + if_lenisnotheapnumber(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->IsHeapNumberMap(assembler->LoadMap(len)),
|
| + &if_lenisheapnumber, &if_lenisnotheapnumber);
|
| +
|
| + assembler->Bind(&if_lenisheapnumber);
|
| + {
|
| + // Load the floating-point value of {len}.
|
| + Node* len_value = assembler->LoadHeapNumberValue(len);
|
| +
|
| + // Check if {len} is not greater than zero.
|
| + assembler->GotoUnless(assembler->Float64GreaterThan(
|
| + len_value, assembler->Float64Constant(0.0)),
|
| + &return_zero);
|
| +
|
| + // Check if {len} is greater than or equal to 2^53-1.
|
| + assembler->GotoIf(
|
| + assembler->Float64GreaterThanOrEqual(
|
| + len_value, assembler->Float64Constant(kMaxSafeInteger)),
|
| + &return_two53minus1);
|
| +
|
| + // Round the {len} towards -Infinity.
|
| + Node* value = assembler->Float64Floor(len_value);
|
| + Node* result = assembler->ChangeFloat64ToTagged(value);
|
| + assembler->Return(result);
|
| + }
|
| +
|
| + assembler->Bind(&if_lenisnotheapnumber);
|
| + {
|
| + // Need to convert {len} to a Number first.
|
| + Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate());
|
| + var_len.Bind(assembler->CallStub(callable, context, len));
|
| + assembler->Goto(&loop);
|
| + }
|
| +
|
| + assembler->Bind(&return_len);
|
| + assembler->Return(var_len.value());
|
| +
|
| + assembler->Bind(&return_two53minus1);
|
| + assembler->Return(assembler->NumberConstant(kMaxSafeInteger));
|
| +
|
| + assembler->Bind(&return_zero);
|
| + assembler->Return(assembler->SmiConstant(Smi::FromInt(0)));
|
| + }
|
| +}
|
| +
|
| +void Builtins::Generate_ToInteger(CodeStubAssembler* assembler) {
|
| + typedef TypeConversionDescriptor Descriptor;
|
| +
|
| + compiler::Node* input = assembler->Parameter(Descriptor::kArgument);
|
| + compiler::Node* context = assembler->Parameter(Descriptor::kContext);
|
| +
|
| + assembler->Return(assembler->ToInteger(context, input));
|
| +}
|
| +
|
| +// ES6 section 7.1.13 ToObject (argument)
|
| +void Builtins::Generate_ToObject(CodeStubAssembler* assembler) {
|
| + typedef compiler::Node Node;
|
| + typedef CodeStubAssembler::Label Label;
|
| + typedef CodeStubAssembler::Variable Variable;
|
| + typedef TypeConversionDescriptor Descriptor;
|
| +
|
| + Label if_number(assembler, Label::kDeferred), if_notsmi(assembler),
|
| + if_jsreceiver(assembler), if_noconstructor(assembler, Label::kDeferred),
|
| + if_wrapjsvalue(assembler);
|
| +
|
| + Node* object = assembler->Parameter(Descriptor::kArgument);
|
| + Node* context = assembler->Parameter(Descriptor::kContext);
|
| +
|
| + Variable constructor_function_index_var(assembler,
|
| + MachineType::PointerRepresentation());
|
| +
|
| + assembler->Branch(assembler->WordIsSmi(object), &if_number, &if_notsmi);
|
| +
|
| + assembler->Bind(&if_notsmi);
|
| + Node* map = assembler->LoadMap(object);
|
| +
|
| + assembler->GotoIf(assembler->IsHeapNumberMap(map), &if_number);
|
| +
|
| + Node* instance_type = assembler->LoadMapInstanceType(map);
|
| + assembler->GotoIf(assembler->IsJSReceiverInstanceType(instance_type),
|
| + &if_jsreceiver);
|
| +
|
| + Node* constructor_function_index =
|
| + assembler->LoadMapConstructorFunctionIndex(map);
|
| + assembler->GotoIf(assembler->WordEqual(constructor_function_index,
|
| + assembler->IntPtrConstant(
|
| + Map::kNoConstructorFunctionIndex)),
|
| + &if_noconstructor);
|
| + constructor_function_index_var.Bind(constructor_function_index);
|
| + assembler->Goto(&if_wrapjsvalue);
|
| +
|
| + assembler->Bind(&if_number);
|
| + constructor_function_index_var.Bind(
|
| + assembler->IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
|
| + assembler->Goto(&if_wrapjsvalue);
|
| +
|
| + assembler->Bind(&if_wrapjsvalue);
|
| + Node* native_context = assembler->LoadNativeContext(context);
|
| + Node* constructor = assembler->LoadFixedArrayElement(
|
| + native_context, constructor_function_index_var.value(), 0,
|
| + CodeStubAssembler::INTPTR_PARAMETERS);
|
| + Node* initial_map = assembler->LoadObjectField(
|
| + constructor, JSFunction::kPrototypeOrInitialMapOffset);
|
| + Node* js_value = assembler->Allocate(JSValue::kSize);
|
| + assembler->StoreMapNoWriteBarrier(js_value, initial_map);
|
| + assembler->StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset,
|
| + Heap::kEmptyFixedArrayRootIndex);
|
| + assembler->StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
|
| + Heap::kEmptyFixedArrayRootIndex);
|
| + assembler->StoreObjectField(js_value, JSValue::kValueOffset, object);
|
| + assembler->Return(js_value);
|
| +
|
| + assembler->Bind(&if_noconstructor);
|
| + assembler->TailCallRuntime(
|
| + Runtime::kThrowUndefinedOrNullToObject, context,
|
| + assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
|
| + "ToObject", TENURED)));
|
| +
|
| + assembler->Bind(&if_jsreceiver);
|
| + assembler->Return(object);
|
| +}
|
| +
|
| +// ES6 section 12.5.5 typeof operator
|
| +void Builtins::Generate_Typeof(CodeStubAssembler* assembler) {
|
| + typedef compiler::Node Node;
|
| + typedef TypeofDescriptor Descriptor;
|
| +
|
| + Node* object = assembler->Parameter(Descriptor::kObject);
|
| + Node* context = assembler->Parameter(Descriptor::kContext);
|
| +
|
| + assembler->Return(assembler->Typeof(object, context));
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace v8
|
|
|