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) { |