| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index 5456cd5b4f3b277811ac5de80078def8b745d47a..be780bf92802a8f4828eac591f4af1d2d020f74b 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -4187,6 +4187,199 @@ BUILTIN(ObjectProtoToString) {
|
| return *result;
|
| }
|
|
|
| +// -----------------------------------------------------------------------------
|
| +// ES6 section 21.1 String Objects
|
| +
|
| +// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
|
| +void Builtins::Generate_StringPrototypeCharAt(
|
| + compiler::CodeStubAssembler* assembler) {
|
| + typedef compiler::CodeStubAssembler::Label Label;
|
| + typedef compiler::Node Node;
|
| + typedef compiler::CodeStubAssembler::Variable Variable;
|
| +
|
| + Node* receiver = assembler->Parameter(0);
|
| + Node* position = assembler->Parameter(1);
|
| + Node* context = assembler->Parameter(4);
|
| +
|
| + // Check that {receiver} is coercible to Object and convert it to a String.
|
| + receiver =
|
| + assembler->ToThisString(context, receiver, "String.prototype.charAt");
|
| +
|
| + // Convert the {position} to a Smi and check that it's in bounds of the
|
| + // {receiver}.
|
| + // TODO(bmeurer): Find an abstraction for this!
|
| + {
|
| + // Check if the {position} is already a Smi.
|
| + Variable var_position(assembler, MachineRepresentation::kTagged);
|
| + var_position.Bind(position);
|
| + Label if_positionissmi(assembler),
|
| + if_positionisnotsmi(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
|
| + &if_positionisnotsmi);
|
| + assembler->Bind(&if_positionisnotsmi);
|
| + {
|
| + // Convert the {position} to an Integer via the ToIntegerStub.
|
| + Callable callable = CodeFactory::ToInteger(assembler->isolate());
|
| + Node* index = assembler->CallStub(callable, context, position);
|
| +
|
| + // Check if the resulting {index} is now a Smi.
|
| + Label if_indexissmi(assembler, Label::kDeferred),
|
| + if_indexisnotsmi(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
|
| + &if_indexisnotsmi);
|
| +
|
| + assembler->Bind(&if_indexissmi);
|
| + {
|
| + var_position.Bind(index);
|
| + assembler->Goto(&if_positionissmi);
|
| + }
|
| +
|
| + assembler->Bind(&if_indexisnotsmi);
|
| + {
|
| + // The ToIntegerStub canonicalizes everything in Smi range to Smi
|
| + // representation, so any HeapNumber returned is not in Smi range.
|
| + // The only exception here is -0.0, which we treat as 0.
|
| + Node* index_value = assembler->LoadHeapNumberValue(index);
|
| + Label if_indexiszero(assembler, Label::kDeferred),
|
| + if_indexisnotzero(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->Float64Equal(
|
| + index_value, assembler->Float64Constant(0.0)),
|
| + &if_indexiszero, &if_indexisnotzero);
|
| +
|
| + assembler->Bind(&if_indexiszero);
|
| + {
|
| + var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
|
| + assembler->Goto(&if_positionissmi);
|
| + }
|
| +
|
| + assembler->Bind(&if_indexisnotzero);
|
| + {
|
| + // The {index} is some other integral Number, that is definitely
|
| + // neither -0.0 nor in Smi range.
|
| + assembler->Return(assembler->EmptyStringConstant());
|
| + }
|
| + }
|
| + }
|
| + assembler->Bind(&if_positionissmi);
|
| + position = var_position.value();
|
| +
|
| + // Determine the actual length of the {receiver} String.
|
| + Node* receiver_length =
|
| + assembler->LoadObjectField(receiver, String::kLengthOffset);
|
| +
|
| + // Return "" if the Smi {position} is outside the bounds of the {receiver}.
|
| + Label if_positioninbounds(assembler),
|
| + if_positionnotinbounds(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
|
| + &if_positionnotinbounds, &if_positioninbounds);
|
| + assembler->Bind(&if_positionnotinbounds);
|
| + assembler->Return(assembler->EmptyStringConstant());
|
| + assembler->Bind(&if_positioninbounds);
|
| + }
|
| +
|
| + // Load the character code at the {position} from the {receiver}.
|
| + Node* code = assembler->StringCharCodeAt(receiver, position);
|
| +
|
| + // And return the single character string with only that {code}.
|
| + Node* result = assembler->StringFromCharCode(code);
|
| + assembler->Return(result);
|
| +}
|
| +
|
| +// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
|
| +void Builtins::Generate_StringPrototypeCharCodeAt(
|
| + compiler::CodeStubAssembler* assembler) {
|
| + typedef compiler::CodeStubAssembler::Label Label;
|
| + typedef compiler::Node Node;
|
| + typedef compiler::CodeStubAssembler::Variable Variable;
|
| +
|
| + Node* receiver = assembler->Parameter(0);
|
| + Node* position = assembler->Parameter(1);
|
| + Node* context = assembler->Parameter(4);
|
| +
|
| + // Check that {receiver} is coercible to Object and convert it to a String.
|
| + receiver =
|
| + assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
|
| +
|
| + // Convert the {position} to a Smi and check that it's in bounds of the
|
| + // {receiver}.
|
| + // TODO(bmeurer): Find an abstraction for this!
|
| + {
|
| + // Check if the {position} is already a Smi.
|
| + Variable var_position(assembler, MachineRepresentation::kTagged);
|
| + var_position.Bind(position);
|
| + Label if_positionissmi(assembler),
|
| + if_positionisnotsmi(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
|
| + &if_positionisnotsmi);
|
| + assembler->Bind(&if_positionisnotsmi);
|
| + {
|
| + // Convert the {position} to an Integer via the ToIntegerStub.
|
| + Callable callable = CodeFactory::ToInteger(assembler->isolate());
|
| + Node* index = assembler->CallStub(callable, context, position);
|
| +
|
| + // Check if the resulting {index} is now a Smi.
|
| + Label if_indexissmi(assembler, Label::kDeferred),
|
| + if_indexisnotsmi(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
|
| + &if_indexisnotsmi);
|
| +
|
| + assembler->Bind(&if_indexissmi);
|
| + {
|
| + var_position.Bind(index);
|
| + assembler->Goto(&if_positionissmi);
|
| + }
|
| +
|
| + assembler->Bind(&if_indexisnotsmi);
|
| + {
|
| + // The ToIntegerStub canonicalizes everything in Smi range to Smi
|
| + // representation, so any HeapNumber returned is not in Smi range.
|
| + // The only exception here is -0.0, which we treat as 0.
|
| + Node* index_value = assembler->LoadHeapNumberValue(index);
|
| + Label if_indexiszero(assembler, Label::kDeferred),
|
| + if_indexisnotzero(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->Float64Equal(
|
| + index_value, assembler->Float64Constant(0.0)),
|
| + &if_indexiszero, &if_indexisnotzero);
|
| +
|
| + assembler->Bind(&if_indexiszero);
|
| + {
|
| + var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
|
| + assembler->Goto(&if_positionissmi);
|
| + }
|
| +
|
| + assembler->Bind(&if_indexisnotzero);
|
| + {
|
| + // The {index} is some other integral Number, that is definitely
|
| + // neither -0.0 nor in Smi range.
|
| + assembler->Return(assembler->NaNConstant());
|
| + }
|
| + }
|
| + }
|
| + assembler->Bind(&if_positionissmi);
|
| + position = var_position.value();
|
| +
|
| + // Determine the actual length of the {receiver} String.
|
| + Node* receiver_length =
|
| + assembler->LoadObjectField(receiver, String::kLengthOffset);
|
| +
|
| + // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
|
| + Label if_positioninbounds(assembler),
|
| + if_positionnotinbounds(assembler, Label::kDeferred);
|
| + assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
|
| + &if_positionnotinbounds, &if_positioninbounds);
|
| + assembler->Bind(&if_positionnotinbounds);
|
| + assembler->Return(assembler->NaNConstant());
|
| + assembler->Bind(&if_positioninbounds);
|
| + }
|
| +
|
| + // Load the character at the {position} from the {receiver}.
|
| + Node* value = assembler->StringCharCodeAt(receiver, position);
|
| + Node* result = assembler->SmiFromWord32(value);
|
| + assembler->Return(result);
|
| +}
|
| +
|
| +// -----------------------------------------------------------------------------
|
| +// ES6 section 21.1 ArrayBuffer Objects
|
|
|
| // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
|
| BUILTIN(ArrayBufferConstructor) {
|
|
|