Commit 8e19a2c4 authored by danno's avatar danno Committed by Commit bot

[stubs] Ensure generated CalculateNewElementsCapacity is identical to runtime version

The original TF port didn't maintain the same semantics as the CS/runtime implementation, and in fact introduced a bug that grew capacity too slowly on
32-bit platforms.

R=ishell@chromium.org
LOG=N

Review-Url: https://codereview.chromium.org/2617393002
Cr-Commit-Position: refs/heads/master@{#42155}
parent 5560bbb4
......@@ -1492,8 +1492,7 @@ Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
Node* new_length =
IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode);
GotoUnless(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits);
Node* new_capacity = CalculateNewElementsCapacity(
IntPtrOrSmiAdd(new_length, IntPtrOrSmiConstant(1, mode), mode), mode);
Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind,
kind, capacity, new_capacity, mode,
&pre_bailout));
......@@ -2346,18 +2345,10 @@ Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array,
Node* CodeStubAssembler::CalculateNewElementsCapacity(Node* old_capacity,
ParameterMode mode) {
if (mode == SMI_PARAMETERS) {
old_capacity = BitcastTaggedToWord(old_capacity);
}
Node* half_old_capacity = WordShr(old_capacity, IntPtrConstant(1));
Node* new_capacity = IntPtrAdd(half_old_capacity, old_capacity);
Node* unconditioned_result = IntPtrAdd(new_capacity, IntPtrConstant(16));
if (mode == SMI_PARAMETERS) {
return SmiAnd(BitcastWordToTaggedSigned(unconditioned_result),
SmiConstant(-1));
} else {
return unconditioned_result;
}
Node* half_old_capacity = WordOrSmiShr(old_capacity, 1, mode);
Node* new_capacity = IntPtrOrSmiAdd(half_old_capacity, old_capacity, mode);
Node* padding = IntPtrOrSmiConstant(16, mode);
return IntPtrOrSmiAdd(new_capacity, padding, mode);
}
Node* CodeStubAssembler::TryGrowElementsCapacity(Node* object, Node* elements,
......
......@@ -172,18 +172,35 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
SMI_ARITHMETIC_BINOP(SmiSub, IntPtrSub)
SMI_ARITHMETIC_BINOP(SmiAnd, WordAnd)
SMI_ARITHMETIC_BINOP(SmiOr, WordOr)
#undef SMI_ARITHMETIC_BINOP
#define SMI_SHIFT_OP(SmiOpName, IntPtrOpName) \
Node* SmiOpName(Node* a, int shift) { \
return BitcastWordToTaggedSigned( \
IntPtrOpName(BitcastTaggedToWord(a), shift)); \
} \
SMI_ARITHMETIC_BINOP(SmiOpName, IntPtrOpName)
Node* SmiShl(Node* a, int shift) {
return BitcastWordToTaggedSigned(WordShl(BitcastTaggedToWord(a), shift));
}
SMI_SHIFT_OP(SmiShl, WordShl)
SMI_SHIFT_OP(SmiShr, WordShr)
#undef SMI_SHIFT_OP
#undef SMI_ARITHMETIC_BINOP
Node* SmiShr(Node* a, int shift) {
return BitcastWordToTaggedSigned(
WordAnd(WordShr(BitcastTaggedToWord(a), shift),
BitcastTaggedToWord(SmiConstant(-1))));
}
Node* WordOrSmiShl(Node* a, int shift, ParameterMode mode) {
if (mode == SMI_PARAMETERS) {
return SmiShl(a, shift);
} else {
DCHECK_EQ(INTPTR_PARAMETERS, mode);
return WordShl(a, shift);
}
}
Node* WordOrSmiShr(Node* a, int shift, ParameterMode mode) {
if (mode == SMI_PARAMETERS) {
return SmiShr(a, shift);
} else {
DCHECK_EQ(INTPTR_PARAMETERS, mode);
return WordShr(a, shift);
}
}
#define SMI_COMPARISON_OP(SmiOpName, IntPtrOpName) \
Node* SmiOpName(Node* a, Node* b) { \
......
......@@ -2047,6 +2047,71 @@ TEST(CreatePromiseResolvingFunctions) {
CHECK(result_arr->get(1)->IsJSFunction());
}
TEST(NewElementsCapacity) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester data(isolate, 1);
CodeStubAssembler m(data.state());
m.Return(m.SmiTag(m.CalculateNewElementsCapacity(
m.SmiUntag(m.Parameter(0)), CodeStubAssembler::INTPTR_PARAMETERS)));
Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
FunctionTester ft(code, 1);
Handle<Smi> test_value = Handle<Smi>(Smi::FromInt(0), isolate);
Handle<Smi> result_obj =
Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
test_value = Handle<Smi>(Smi::FromInt(1), isolate);
result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
test_value = Handle<Smi>(Smi::FromInt(2), isolate);
result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
test_value = Handle<Smi>(Smi::FromInt(1025), isolate);
result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
}
TEST(NewElementsCapacitySmi) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester data(isolate, 1);
CodeStubAssembler m(data.state());
m.Return(m.CalculateNewElementsCapacity(m.Parameter(0),
CodeStubAssembler::SMI_PARAMETERS));
Handle<Code> code = data.GenerateCode();
code->Print();
CHECK(!code.is_null());
FunctionTester ft(code, 1);
Handle<Smi> test_value = Handle<Smi>(Smi::FromInt(0), isolate);
Handle<Smi> result_obj =
Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
test_value = Handle<Smi>(Smi::FromInt(1), isolate);
result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
test_value = Handle<Smi>(Smi::FromInt(2), isolate);
result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
test_value = Handle<Smi>(Smi::FromInt(1025), isolate);
result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked());
CHECK_EQ(
result_obj->value(),
static_cast<int>(JSObject::NewElementsCapacity(test_value->value())));
}
TEST(AllocateFunctionWithMapAndContext) {
Isolate* isolate(CcTest::InitIsolateOnce());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment