Index: src/code-stubs-hydrogen.cc |
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc |
index fdd2a1d76c26838a0429c4482ac30a370352238f..6e3663273c19a2bdd65baa674bb914831f2c56c3 100644 |
--- a/src/code-stubs-hydrogen.cc |
+++ b/src/code-stubs-hydrogen.cc |
@@ -78,7 +78,8 @@ class CodeStubGraphBuilderBase : public HGraphBuilder { |
Representation representation, |
bool transition_to_field); |
- HValue* BuildPushElement(HValue* object, HValue* value, ElementsKind kind); |
+ HValue* BuildPushElement(HValue* object, HValue* argc, |
+ HValue* argument_elements, ElementsKind kind); |
enum ArgumentClass { |
NONE, |
@@ -782,36 +783,53 @@ Handle<Code> StoreScriptContextFieldStub::GenerateCode() { |
return DoGenerateCode(this); |
} |
-HValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, |
- HValue* value, |
+HValue* CodeStubGraphBuilderBase::BuildPushElement(HValue* object, HValue* argc, |
+ HValue* argument_elements, |
ElementsKind kind) { |
+ // Precheck whether all elements fit into the array. |
+ if (!IsFastObjectElementsKind(kind)) { |
+ LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
+ HValue* start = graph()->GetConstant0(); |
+ HValue* key = builder.BeginBody(start, argc, Token::LT); |
+ { |
+ HInstruction* argument = |
+ Add<HAccessArgumentsAt>(argument_elements, argc, key); |
+ Representation r = IsFastSmiElementsKind(kind) ? Representation::Smi() |
+ : Representation::Double(); |
+ AddUncasted<HForceRepresentation>(argument, r); |
+ } |
+ builder.EndBody(); |
+ } |
+ |
HValue* length = Add<HLoadNamedField>(object, nullptr, |
HObjectAccess::ForArrayLength(kind)); |
- HValue* key = length; |
+ HValue* new_length = AddUncasted<HAdd>(length, argc); |
+ HValue* max_key = AddUncasted<HSub>(new_length, graph()->GetConstant1()); |
+ |
HValue* elements = Add<HLoadNamedField>(object, nullptr, |
HObjectAccess::ForElementsPointer()); |
- elements = BuildCheckForCapacityGrow(object, elements, kind, length, key, |
+ elements = BuildCheckForCapacityGrow(object, elements, kind, length, max_key, |
true, STORE); |
- AddElementAccess(elements, key, value, object, nullptr, kind, STORE); |
- return key; |
+ |
+ LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement); |
+ HValue* start = graph()->GetConstant0(); |
+ HValue* key = builder.BeginBody(start, argc, Token::LT); |
+ { |
+ HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); |
+ HValue* index = AddUncasted<HAdd>(key, length); |
+ AddElementAccess(elements, index, argument, object, nullptr, kind, STORE); |
+ } |
+ builder.EndBody(); |
+ return new_length; |
} |
template <> |
HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { |
// TODO(verwaest): Fix deoptimizer messages. |
HValue* argc = GetArgumentsLength(); |
- IfBuilder arg_check(this); |
- arg_check.If<HCompareNumericAndBranch>(argc, graph()->GetConstant1(), |
- Token::NE); |
- arg_check.ThenDeopt(Deoptimizer::kFastArrayPushFailed); |
- arg_check.End(); |
- |
HInstruction* argument_elements = Add<HArgumentsElements>(false, false); |
HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, |
graph()->GetConstantMinus1()); |
- HInstruction* value = |
- Add<HAccessArgumentsAt>(argument_elements, argc, graph()->GetConstant0()); |
- |
BuildCheckHeapObject(object); |
HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); |
Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY); |
@@ -930,10 +948,9 @@ HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { |
kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE); |
has_smi_elements.Then(); |
{ |
- HValue* smi_value = |
- AddUncasted<HForceRepresentation>(value, Representation::Smi()); |
- HValue* key = BuildPushElement(object, smi_value, FAST_HOLEY_SMI_ELEMENTS); |
- environment()->Push(key); |
+ HValue* new_length = BuildPushElement(object, argc, argument_elements, |
+ FAST_HOLEY_SMI_ELEMENTS); |
+ environment()->Push(new_length); |
} |
has_smi_elements.Else(); |
{ |
@@ -942,8 +959,9 @@ HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { |
kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE); |
has_object_elements.Then(); |
{ |
- HValue* key = BuildPushElement(object, value, FAST_HOLEY_ELEMENTS); |
- environment()->Push(key); |
+ HValue* new_length = BuildPushElement(object, argc, argument_elements, |
+ FAST_HOLEY_ELEMENTS); |
+ environment()->Push(new_length); |
} |
has_object_elements.Else(); |
{ |
@@ -952,11 +970,9 @@ HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { |
kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); |
has_double_elements.Then(); |
{ |
- HValue* double_value = |
- AddUncasted<HForceRepresentation>(value, Representation::Double()); |
- HValue* key = |
- BuildPushElement(object, double_value, FAST_HOLEY_DOUBLE_ELEMENTS); |
- environment()->Push(key); |
+ HValue* new_length = BuildPushElement(object, argc, argument_elements, |
+ FAST_HOLEY_DOUBLE_ELEMENTS); |
+ environment()->Push(new_length); |
} |
has_double_elements.ElseDeopt(Deoptimizer::kFastArrayPushFailed); |
has_double_elements.End(); |
@@ -965,8 +981,7 @@ HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { |
} |
has_smi_elements.End(); |
- HValue* key = environment()->Pop(); |
- return AddUncasted<HAdd>(key, graph()->GetConstant1()); |
+ return environment()->Pop(); |
} |
Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } |