aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-code-stub-assembler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-code-stub-assembler.cc')
-rw-r--r--deps/v8/test/cctest/test-code-stub-assembler.cc1534
1 files changed, 1019 insertions, 515 deletions
diff --git a/deps/v8/test/cctest/test-code-stub-assembler.cc b/deps/v8/test/cctest/test-code-stub-assembler.cc
index da2773fdca..068ef9c3d1 100644
--- a/deps/v8/test/cctest/test-code-stub-assembler.cc
+++ b/deps/v8/test/cctest/test-code-stub-assembler.cc
@@ -3,10 +3,10 @@
// found in the LICENSE file.
#include "src/base/utils/random-number-generator.h"
+#include "src/builtins/builtins-promise.h"
#include "src/code-factory.h"
#include "src/code-stub-assembler.h"
#include "src/compiler/node.h"
-#include "src/ic/stub-cache.h"
#include "src/isolate.h"
#include "test/cctest/compiler/code-assembler-tester.h"
#include "test/cctest/compiler/function-tester.h"
@@ -14,48 +14,49 @@
namespace v8 {
namespace internal {
+using compiler::CodeAssemblerTester;
using compiler::FunctionTester;
using compiler::Node;
-
-typedef compiler::CodeAssemblerTesterImpl<CodeStubAssembler>
- CodeStubAssemblerTester;
+using compiler::CodeAssemblerLabel;
+using compiler::CodeAssemblerVariable;
+using compiler::CodeAssemblerVariableList;
TEST(FixedArrayAccessSmiIndex) {
Isolate* isolate(CcTest::InitIsolateOnce());
- VoidDescriptor descriptor(isolate);
- CodeStubAssemblerTester m(isolate, descriptor);
+ CodeAssemblerTester data(isolate);
+ CodeStubAssembler m(data.state());
Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
array->set(4, Smi::FromInt(733));
m.Return(m.LoadFixedArrayElement(m.HeapConstant(array),
m.SmiTag(m.Int32Constant(4)), 0,
CodeStubAssembler::SMI_PARAMETERS));
- Handle<Code> code = m.GenerateCode();
- FunctionTester ft(descriptor, code);
+ Handle<Code> code = data.GenerateCode();
+ FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call();
CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
}
TEST(LoadHeapNumberValue) {
Isolate* isolate(CcTest::InitIsolateOnce());
- VoidDescriptor descriptor(isolate);
- CodeStubAssemblerTester m(isolate, descriptor);
+ CodeAssemblerTester data(isolate);
+ CodeStubAssembler m(data.state());
Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
- m.Return(m.SmiTag(
+ m.Return(m.SmiFromWord32(
m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number)))));
- Handle<Code> code = m.GenerateCode();
- FunctionTester ft(descriptor, code);
+ Handle<Code> code = data.GenerateCode();
+ FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call();
CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
}
TEST(LoadInstanceType) {
Isolate* isolate(CcTest::InitIsolateOnce());
- VoidDescriptor descriptor(isolate);
- CodeStubAssemblerTester m(isolate, descriptor);
+ CodeAssemblerTester data(isolate);
+ CodeStubAssembler m(data.state());
Handle<HeapObject> undefined = isolate->factory()->undefined_value();
- m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined))));
- Handle<Code> code = m.GenerateCode();
- FunctionTester ft(descriptor, code);
+ m.Return(m.SmiFromWord32(m.LoadInstanceType(m.HeapConstant(undefined))));
+ Handle<Code> code = data.GenerateCode();
+ FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call();
CHECK_EQ(InstanceType::ODDBALL_TYPE,
Handle<Smi>::cast(result.ToHandleChecked())->value());
@@ -63,14 +64,14 @@ TEST(LoadInstanceType) {
TEST(DecodeWordFromWord32) {
Isolate* isolate(CcTest::InitIsolateOnce());
- VoidDescriptor descriptor(isolate);
- CodeStubAssemblerTester m(isolate, descriptor);
+ CodeAssemblerTester data(isolate);
+ CodeStubAssembler m(data.state());
class TestBitField : public BitField<unsigned, 3, 3> {};
m.Return(
m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2f))));
- Handle<Code> code = m.GenerateCode();
- FunctionTester ft(descriptor, code);
+ Handle<Code> code = data.GenerateCode();
+ FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call();
// value = 00101111
// mask = 00111000
@@ -81,11 +82,12 @@ TEST(DecodeWordFromWord32) {
TEST(JSFunction) {
const int kNumParams = 3; // Receiver, left, right.
Isolate* isolate(CcTest::InitIsolateOnce());
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.Return(m.SmiFromWord32(m.Int32Add(m.SmiToWord32(m.Parameter(1)),
m.SmiToWord32(m.Parameter(2)))));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(),
@@ -97,11 +99,12 @@ TEST(JSFunction) {
TEST(ComputeIntegerHash) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.Return(m.SmiFromWord32(m.ComputeIntegerHash(
- m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1)))));
+ m.SmiUntag(m.Parameter(0)), m.SmiToWord32(m.Parameter(1)))));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Smi> hash_seed = isolate->factory()->hash_seed();
@@ -123,10 +126,11 @@ TEST(ComputeIntegerHash) {
TEST(ToString) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.Return(m.ToString(m.Parameter(kNumParams + 2), m.Parameter(0)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<FixedArray> test_cases = isolate->factory()->NewFixedArray(5);
@@ -179,10 +183,11 @@ TEST(ToString) {
TEST(FlattenString) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.Return(m.FlattenString(m.Parameter(0)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<FixedArray> test_cases(isolate->factory()->NewFixedArray(4));
@@ -217,12 +222,13 @@ TEST(FlattenString) {
}
TEST(TryToName) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
+ typedef CodeAssemblerLabel Label;
+ typedef CodeAssemblerVariable Variable;
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 3;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
enum Result { kKeyIsIndex, kKeyIsUnique, kBailout };
{
@@ -261,7 +267,7 @@ TEST(TryToName) {
m.Return(m.BooleanConstant(false));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate);
@@ -352,14 +358,15 @@ void TestEntryToIndex() {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
{
Node* entry = m.SmiUntag(m.Parameter(0));
Node* result = m.EntryToIndex<Dictionary>(entry);
m.Return(m.SmiTag(result));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
// Test a wide range of entries but staying linear in the first 100 entries.
@@ -380,12 +387,13 @@ namespace {
template <typename Dictionary>
void TestNameDictionaryLookup() {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
+ typedef CodeAssemblerLabel Label;
+ typedef CodeAssemblerVariable Variable;
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound };
{
@@ -404,7 +412,7 @@ void TestNameDictionaryLookup() {
m.GotoUnless(
m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
&failed);
- m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_name_index.value()),
+ m.Branch(m.WordEqual(m.SmiUntag(expected_arg), var_name_index.value()),
&passed, &failed);
m.Bind(&if_not_found);
@@ -419,7 +427,7 @@ void TestNameDictionaryLookup() {
m.Return(m.BooleanConstant(false));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
@@ -486,17 +494,18 @@ namespace {
template <typename Dictionary>
void TestNumberDictionaryLookup() {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
+ typedef CodeAssemblerLabel Label;
+ typedef CodeAssemblerVariable Variable;
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound };
{
Node* dictionary = m.Parameter(0);
- Node* key = m.SmiToWord32(m.Parameter(1));
+ Node* key = m.SmiUntag(m.Parameter(1));
Node* expected_result = m.Parameter(2);
Node* expected_arg = m.Parameter(3);
@@ -510,8 +519,8 @@ void TestNumberDictionaryLookup() {
m.GotoUnless(
m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))),
&failed);
- m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_entry.value()),
- &passed, &failed);
+ m.Branch(m.WordEqual(m.SmiUntag(expected_arg), var_entry.value()), &passed,
+ &failed);
m.Bind(&if_not_found);
m.Branch(
@@ -525,7 +534,7 @@ void TestNumberDictionaryLookup() {
m.Return(m.BooleanConstant(false));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
@@ -624,11 +633,12 @@ void AddProperties(Handle<JSObject> object, Handle<Name> names[],
} // namespace
TEST(TryHasOwnProperty) {
- typedef CodeStubAssembler::Label Label;
+ typedef CodeAssemblerLabel Label;
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound, kBailout };
{
@@ -666,7 +676,7 @@ TEST(TryHasOwnProperty) {
m.Return(m.BooleanConstant(false));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
@@ -808,13 +818,14 @@ TEST(TryHasOwnProperty) {
}
TEST(TryGetOwnProperty) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
+ typedef CodeAssemblerLabel Label;
+ typedef CodeAssemblerVariable Variable;
Isolate* isolate(CcTest::InitIsolateOnce());
Factory* factory = isolate->factory();
const int kNumParams = 2;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
Handle<Symbol> not_found_symbol = factory->NewSymbol();
Handle<Symbol> bailout_symbol = factory->NewSymbol();
@@ -843,7 +854,7 @@ TEST(TryGetOwnProperty) {
m.Return(m.HeapConstant(bailout_symbol));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Name> deleted_property_name =
@@ -1026,16 +1037,17 @@ void AddElement(Handle<JSObject> object, uint32_t index, Handle<Object> value,
} // namespace
TEST(TryLookupElement) {
- typedef CodeStubAssembler::Label Label;
+ typedef CodeAssemblerLabel Label;
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 3;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound, kBailout };
{
Node* object = m.Parameter(0);
- Node* index = m.SmiToWord32(m.Parameter(1));
+ Node* index = m.SmiUntag(m.Parameter(1));
Node* expected_result = m.Parameter(2);
Label passed(&m), failed(&m);
@@ -1068,7 +1080,7 @@ TEST(TryLookupElement) {
m.Return(m.BooleanConstant(false));
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Factory* factory = isolate->factory();
@@ -1211,434 +1223,13 @@ TEST(TryLookupElement) {
}
}
-TEST(DeferredCodePhiHints) {
- typedef compiler::Node Node;
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- Isolate* isolate(CcTest::InitIsolateOnce());
- VoidDescriptor descriptor(isolate);
- CodeStubAssemblerTester m(isolate, descriptor);
- Label block1(&m, Label::kDeferred);
- m.Goto(&block1);
- m.Bind(&block1);
- {
- Variable var_object(&m, MachineRepresentation::kTagged);
- Label loop(&m, &var_object);
- var_object.Bind(m.IntPtrConstant(0));
- m.Goto(&loop);
- m.Bind(&loop);
- {
- Node* map = m.LoadMap(var_object.value());
- var_object.Bind(map);
- m.Goto(&loop);
- }
- }
- CHECK(!m.GenerateCode().is_null());
-}
-
-TEST(TestOutOfScopeVariable) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- Isolate* isolate(CcTest::InitIsolateOnce());
- VoidDescriptor descriptor(isolate);
- CodeStubAssemblerTester m(isolate, descriptor);
- Label block1(&m);
- Label block2(&m);
- Label block3(&m);
- Label block4(&m);
- m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4);
- m.Bind(&block4);
- {
- Variable var_object(&m, MachineRepresentation::kTagged);
- m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2,
- &block3);
-
- m.Bind(&block2);
- var_object.Bind(m.IntPtrConstant(55));
- m.Goto(&block1);
-
- m.Bind(&block3);
- var_object.Bind(m.IntPtrConstant(66));
- m.Goto(&block1);
- }
- m.Bind(&block1);
- CHECK(!m.GenerateCode().is_null());
-}
-
-namespace {
-
-void TestStubCacheOffsetCalculation(StubCache::Table table) {
- Isolate* isolate(CcTest::InitIsolateOnce());
- const int kNumParams = 2;
- CodeStubAssemblerTester m(isolate, kNumParams);
-
- {
- Node* name = m.Parameter(0);
- Node* map = m.Parameter(1);
- Node* primary_offset = m.StubCachePrimaryOffset(name, map);
- Node* result;
- if (table == StubCache::kPrimary) {
- result = primary_offset;
- } else {
- CHECK_EQ(StubCache::kSecondary, table);
- result = m.StubCacheSecondaryOffset(name, primary_offset);
- }
- m.Return(m.SmiFromWord32(result));
- }
-
- Handle<Code> code = m.GenerateCode();
- FunctionTester ft(code, kNumParams);
-
- Factory* factory = isolate->factory();
- Handle<Name> names[] = {
- factory->NewSymbol(),
- factory->InternalizeUtf8String("a"),
- factory->InternalizeUtf8String("bb"),
- factory->InternalizeUtf8String("ccc"),
- factory->NewPrivateSymbol(),
- factory->InternalizeUtf8String("dddd"),
- factory->InternalizeUtf8String("eeeee"),
- factory->InternalizeUtf8String("name"),
- factory->NewSymbol(),
- factory->NewPrivateSymbol(),
- };
-
- Handle<Map> maps[] = {
- Handle<Map>(nullptr, isolate),
- factory->cell_map(),
- Map::Create(isolate, 0),
- factory->meta_map(),
- factory->code_map(),
- Map::Create(isolate, 0),
- factory->hash_table_map(),
- factory->symbol_map(),
- factory->string_map(),
- Map::Create(isolate, 0),
- factory->sloppy_arguments_elements_map(),
- };
-
- for (size_t name_index = 0; name_index < arraysize(names); name_index++) {
- Handle<Name> name = names[name_index];
- for (size_t map_index = 0; map_index < arraysize(maps); map_index++) {
- Handle<Map> map = maps[map_index];
-
- int expected_result;
- {
- int primary_offset = StubCache::PrimaryOffsetForTesting(*name, *map);
- if (table == StubCache::kPrimary) {
- expected_result = primary_offset;
- } else {
- expected_result =
- StubCache::SecondaryOffsetForTesting(*name, primary_offset);
- }
- }
- Handle<Object> result = ft.Call(name, map).ToHandleChecked();
-
- Smi* expected = Smi::FromInt(expected_result & Smi::kMaxValue);
- CHECK_EQ(expected, Smi::cast(*result));
- }
- }
-}
-
-} // namespace
-
-TEST(StubCachePrimaryOffset) {
- TestStubCacheOffsetCalculation(StubCache::kPrimary);
-}
-
-TEST(StubCacheSecondaryOffset) {
- TestStubCacheOffsetCalculation(StubCache::kSecondary);
-}
-
-namespace {
-
-Handle<Code> CreateCodeWithFlags(Code::Flags flags) {
- Isolate* isolate(CcTest::InitIsolateOnce());
- CodeStubAssemblerTester m(isolate, flags);
- m.Return(m.UndefinedConstant());
- return m.GenerateCodeCloseAndEscape();
-}
-
-} // namespace
-
-TEST(TryProbeStubCache) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- Isolate* isolate(CcTest::InitIsolateOnce());
- const int kNumParams = 3;
- CodeStubAssemblerTester m(isolate, kNumParams);
-
- Code::Kind ic_kind = Code::LOAD_IC;
- StubCache stub_cache(isolate, ic_kind);
- stub_cache.Clear();
-
- {
- Node* receiver = m.Parameter(0);
- Node* name = m.Parameter(1);
- Node* expected_handler = m.Parameter(2);
-
- Label passed(&m), failed(&m);
-
- Variable var_handler(&m, MachineRepresentation::kTagged);
- Label if_handler(&m), if_miss(&m);
-
- m.TryProbeStubCache(&stub_cache, receiver, name, &if_handler, &var_handler,
- &if_miss);
- m.Bind(&if_handler);
- m.Branch(m.WordEqual(expected_handler, var_handler.value()), &passed,
- &failed);
-
- m.Bind(&if_miss);
- m.Branch(m.WordEqual(expected_handler, m.IntPtrConstant(0)), &passed,
- &failed);
-
- m.Bind(&passed);
- m.Return(m.BooleanConstant(true));
-
- m.Bind(&failed);
- m.Return(m.BooleanConstant(false));
- }
-
- Handle<Code> code = m.GenerateCode();
- FunctionTester ft(code, kNumParams);
-
- std::vector<Handle<Name>> names;
- std::vector<Handle<JSObject>> receivers;
- std::vector<Handle<Code>> handlers;
-
- base::RandomNumberGenerator rand_gen(FLAG_random_seed);
-
- Factory* factory = isolate->factory();
-
- // Generate some number of names.
- for (int i = 0; i < StubCache::kPrimaryTableSize / 7; i++) {
- Handle<Name> name;
- switch (rand_gen.NextInt(3)) {
- case 0: {
- // Generate string.
- std::stringstream ss;
- ss << "s" << std::hex
- << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize);
- name = factory->InternalizeUtf8String(ss.str().c_str());
- break;
- }
- case 1: {
- // Generate number string.
- std::stringstream ss;
- ss << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize);
- name = factory->InternalizeUtf8String(ss.str().c_str());
- break;
- }
- case 2: {
- // Generate symbol.
- name = factory->NewSymbol();
- break;
- }
- default:
- UNREACHABLE();
- }
- names.push_back(name);
- }
-
- // Generate some number of receiver maps and receivers.
- for (int i = 0; i < StubCache::kSecondaryTableSize / 2; i++) {
- Handle<Map> map = Map::Create(isolate, 0);
- receivers.push_back(factory->NewJSObjectFromMap(map));
- }
-
- // Generate some number of handlers.
- for (int i = 0; i < 30; i++) {
- Code::Flags flags =
- Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(ic_kind));
- handlers.push_back(CreateCodeWithFlags(flags));
- }
-
- // Ensure that GC does happen because from now on we are going to fill our
- // own stub cache instance with raw values.
- DisallowHeapAllocation no_gc;
-
- // Populate {stub_cache}.
- const int N = StubCache::kPrimaryTableSize + StubCache::kSecondaryTableSize;
- for (int i = 0; i < N; i++) {
- int index = rand_gen.NextInt();
- Handle<Name> name = names[index % names.size()];
- Handle<JSObject> receiver = receivers[index % receivers.size()];
- Handle<Code> handler = handlers[index % handlers.size()];
- stub_cache.Set(*name, receiver->map(), *handler);
- }
-
- // Perform some queries.
- bool queried_existing = false;
- bool queried_non_existing = false;
- for (int i = 0; i < N; i++) {
- int index = rand_gen.NextInt();
- Handle<Name> name = names[index % names.size()];
- Handle<JSObject> receiver = receivers[index % receivers.size()];
- Object* handler = stub_cache.Get(*name, receiver->map());
- if (handler == nullptr) {
- queried_non_existing = true;
- } else {
- queried_existing = true;
- }
-
- Handle<Object> expected_handler(handler, isolate);
- ft.CheckTrue(receiver, name, expected_handler);
- }
-
- for (int i = 0; i < N; i++) {
- int index1 = rand_gen.NextInt();
- int index2 = rand_gen.NextInt();
- Handle<Name> name = names[index1 % names.size()];
- Handle<JSObject> receiver = receivers[index2 % receivers.size()];
- Object* handler = stub_cache.Get(*name, receiver->map());
- if (handler == nullptr) {
- queried_non_existing = true;
- } else {
- queried_existing = true;
- }
-
- Handle<Object> expected_handler(handler, isolate);
- ft.CheckTrue(receiver, name, expected_handler);
- }
- // Ensure we performed both kind of queries.
- CHECK(queried_existing && queried_non_existing);
-}
-
-TEST(GotoIfException) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- Isolate* isolate(CcTest::InitIsolateOnce());
-
- const int kNumParams = 1;
- // Emulate TFJ builtin
- CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN);
-
- Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
- Node* to_string_tag =
- m.HeapConstant(isolate->factory()->to_string_tag_symbol());
- Variable exception(&m, MachineRepresentation::kTagged);
-
- Label exception_handler(&m);
- Callable to_string = CodeFactory::ToString(isolate);
- Node* string = m.CallStub(to_string, context, to_string_tag);
- m.GotoIfException(string, &exception_handler, &exception);
- m.Return(string);
-
- m.Bind(&exception_handler);
- m.Return(exception.value());
-
- Handle<Code> code = m.GenerateCode();
- CHECK(!code.is_null());
-
- FunctionTester ft(code, kNumParams);
- Handle<Object> result = ft.Call().ToHandleChecked();
-
- // Should be a TypeError
- CHECK(result->IsJSObject());
-
- Handle<Object> constructor =
- Object::GetPropertyOrElement(result,
- isolate->factory()->constructor_string())
- .ToHandleChecked();
- CHECK(constructor->SameValue(*isolate->type_error_function()));
-}
-
-TEST(GotoIfExceptionMultiple) {
- typedef CodeStubAssembler::Label Label;
- typedef CodeStubAssembler::Variable Variable;
- Isolate* isolate(CcTest::InitIsolateOnce());
-
- const int kNumParams = 4; // receiver, first, second, third
- // Emulate TFJ builtin
- CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN);
-
- Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
- Node* first_value = m.Parameter(0);
- Node* second_value = m.Parameter(1);
- Node* third_value = m.Parameter(2);
-
- Label exception_handler1(&m);
- Label exception_handler2(&m);
- Label exception_handler3(&m);
- Variable return_value(&m, MachineRepresentation::kWord32);
- Variable error(&m, MachineRepresentation::kTagged);
-
- return_value.Bind(m.Int32Constant(0));
-
- // try { return ToString(param1) } catch (e) { ... }
- Callable to_string = CodeFactory::ToString(isolate);
- Node* string = m.CallStub(to_string, context, first_value);
- m.GotoIfException(string, &exception_handler1, &error);
- m.Return(string);
-
- // try { ToString(param2); return 7 } catch (e) { ... }
- m.Bind(&exception_handler1);
- return_value.Bind(m.Int32Constant(7));
- error.Bind(m.UndefinedConstant());
- string = m.CallStub(to_string, context, second_value);
- m.GotoIfException(string, &exception_handler2, &error);
- m.Return(m.SmiFromWord32(return_value.value()));
-
- // try { ToString(param3); return 7 & ~2; } catch (e) { return e; }
- m.Bind(&exception_handler2);
- // Return returnValue & ~2
- error.Bind(m.UndefinedConstant());
- string = m.CallStub(to_string, context, third_value);
- m.GotoIfException(string, &exception_handler3, &error);
- m.Return(m.SmiFromWord32(
- m.Word32And(return_value.value(),
- m.Word32Xor(m.Int32Constant(2), m.Int32Constant(-1)))));
-
- m.Bind(&exception_handler3);
- m.Return(error.value());
-
- Handle<Code> code = m.GenerateCode();
- CHECK(!code.is_null());
-
- FunctionTester ft(code, kNumParams);
-
- Handle<Object> result;
- // First handler does not throw, returns result of first value
- result = ft.Call(isolate->factory()->undefined_value(),
- isolate->factory()->to_string_tag_symbol())
- .ToHandleChecked();
- CHECK(String::cast(*result)->IsOneByteEqualTo(OneByteVector("undefined")));
-
- // First handler returns a number
- result = ft.Call(isolate->factory()->to_string_tag_symbol(),
- isolate->factory()->undefined_value())
- .ToHandleChecked();
- CHECK_EQ(7, Smi::cast(*result)->value());
-
- // First handler throws, second handler returns a number
- result = ft.Call(isolate->factory()->to_string_tag_symbol(),
- isolate->factory()->to_primitive_symbol())
- .ToHandleChecked();
- CHECK_EQ(7 & ~2, Smi::cast(*result)->value());
-
- // First handler throws, second handler throws, third handler returns thrown
- // value.
- result = ft.Call(isolate->factory()->to_string_tag_symbol(),
- isolate->factory()->to_primitive_symbol(),
- isolate->factory()->unscopables_symbol())
- .ToHandleChecked();
-
- // Should be a TypeError
- CHECK(result->IsJSObject());
-
- Handle<Object> constructor =
- Object::GetPropertyOrElement(result,
- isolate->factory()->constructor_string())
- .ToHandleChecked();
- CHECK(constructor->SameValue(*isolate->type_error_function()));
-}
-
TEST(AllocateJSObjectFromMap) {
Isolate* isolate(CcTest::InitIsolateOnce());
Factory* factory = isolate->factory();
const int kNumParams = 3;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
{
Node* map = m.Parameter(0);
@@ -1650,7 +1241,7 @@ TEST(AllocateJSObjectFromMap) {
m.Return(result);
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<Map> maps[] = {
@@ -1701,7 +1292,8 @@ TEST(AllocateNameDictionary) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
{
Node* capacity = m.Parameter(0);
@@ -1709,7 +1301,7 @@ TEST(AllocateNameDictionary) {
m.Return(result);
}
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams);
{
@@ -1729,16 +1321,17 @@ TEST(PopAndReturnConstant) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- const int kNumProgramaticParams = 2;
- CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams);
+ const int kNumProgrammaticParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams);
+ CodeStubAssembler m(data.state());
// Call a function that return |kNumProgramaticParams| parameters in addition
// to those specified by the static descriptor. |kNumProgramaticParams| is
// specified as a constant.
- m.PopAndReturn(m.Int32Constant(kNumProgramaticParams),
+ m.PopAndReturn(m.Int32Constant(kNumProgrammaticParams),
m.SmiConstant(Smi::FromInt(1234)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
FunctionTester ft(code, kNumParams);
@@ -1757,8 +1350,9 @@ TEST(PopAndReturnVariable) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- const int kNumProgramaticParams = 2;
- CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams);
+ const int kNumProgrammaticParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams);
+ CodeStubAssembler m(data.state());
// Call a function that return |kNumProgramaticParams| parameters in addition
// to those specified by the static descriptor. |kNumProgramaticParams| is
@@ -1766,7 +1360,7 @@ TEST(PopAndReturnVariable) {
// a constant.
m.PopAndReturn(m.SmiUntag(m.Parameter(1)), m.SmiConstant(Smi::FromInt(1234)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
FunctionTester ft(code, kNumParams);
@@ -1775,7 +1369,7 @@ TEST(PopAndReturnVariable) {
result = ft.Call(isolate->factory()->undefined_value(),
Handle<Smi>(Smi::FromInt(1234), isolate),
isolate->factory()->undefined_value(),
- Handle<Smi>(Smi::FromInt(kNumProgramaticParams), isolate))
+ Handle<Smi>(Smi::FromInt(kNumProgrammaticParams), isolate))
.ToHandleChecked();
CHECK_EQ(1234, Handle<Smi>::cast(result)->value());
}
@@ -1784,7 +1378,9 @@ TEST(PopAndReturnVariable) {
TEST(OneToTwoByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce());
- CodeStubAssemblerTester m(isolate, 2);
+ const int kNumParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@@ -1793,7 +1389,7 @@ TEST(OneToTwoByteStringCopy) {
CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
@@ -1818,7 +1414,9 @@ TEST(OneToTwoByteStringCopy) {
TEST(OneToOneByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce());
- CodeStubAssemblerTester m(isolate, 2);
+ const int kNumParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@@ -1827,7 +1425,7 @@ TEST(OneToOneByteStringCopy) {
CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
@@ -1852,7 +1450,9 @@ TEST(OneToOneByteStringCopy) {
TEST(OneToOneByteStringCopyNonZeroStart) {
Isolate* isolate(CcTest::InitIsolateOnce());
- CodeStubAssemblerTester m(isolate, 2);
+ const int kNumParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@@ -1861,7 +1461,7 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
@@ -1883,7 +1483,9 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
TEST(TwoToTwoByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce());
- CodeStubAssemblerTester m(isolate, 2);
+ const int kNumParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@@ -1892,7 +1494,7 @@ TEST(TwoToTwoByteStringCopy) {
CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0)));
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
uc16 array1[] = {2000, 2001, 2002, 2003, 2004};
@@ -1921,9 +1523,10 @@ TEST(Arguments) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
- CodeStubArguments arguments(&m, m.IntPtrConstant(3));
+ CodeStubArguments arguments(&m, m.Int32Constant(3));
CSA_ASSERT(
&m, m.WordEqual(arguments.AtIndex(0), m.SmiConstant(Smi::FromInt(12))));
@@ -1934,7 +1537,7 @@ TEST(Arguments) {
m.Return(arguments.GetReceiver());
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
FunctionTester ft(code, kNumParams);
@@ -1950,23 +1553,22 @@ TEST(ArgumentsForEach) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4;
- CodeStubAssemblerTester m(isolate, kNumParams);
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
- CodeStubArguments arguments(&m, m.IntPtrConstant(3));
+ CodeStubArguments arguments(&m, m.Int32Constant(3));
- CodeStubAssemblerTester::Variable sum(&m,
- MachineType::PointerRepresentation());
- CodeStubAssemblerTester::VariableList list({&sum}, m.zone());
+ CodeAssemblerVariable sum(&m, MachineRepresentation::kTagged);
+ CodeAssemblerVariableList list({&sum}, m.zone());
- sum.Bind(m.IntPtrConstant(0));
+ sum.Bind(m.SmiConstant(0));
- arguments.ForEach(list, [&m, &sum](CodeStubAssembler* assembler, Node* arg) {
- sum.Bind(assembler->IntPtrAdd(sum.value(), arg));
- });
+ arguments.ForEach(
+ list, [&m, &sum](Node* arg) { sum.Bind(m.SmiAdd(sum.value(), arg)); });
m.Return(sum.value());
- Handle<Code> code = m.GenerateCode();
+ Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null());
FunctionTester ft(code, kNumParams);
@@ -1978,5 +1580,907 @@ TEST(ArgumentsForEach) {
CHECK_EQ(Smi::FromInt(12 + 13 + 14), *result);
}
+TEST(IsDebugActive) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+
+ CodeAssemblerLabel if_active(&m), if_not_active(&m);
+
+ m.Branch(m.IsDebugActive(), &if_active, &if_not_active);
+ m.Bind(&if_active);
+ m.Return(m.TrueConstant());
+ m.Bind(&if_not_active);
+ m.Return(m.FalseConstant());
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ CHECK_EQ(false, isolate->debug()->is_active());
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+
+ bool* debug_is_active = reinterpret_cast<bool*>(
+ ExternalReference::debug_is_active_address(isolate).address());
+
+ // Cheat to enable debug (TODO: do this properly).
+ *debug_is_active = true;
+
+ result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->true_value(), *result);
+
+ // Reset debug mode.
+ *debug_is_active = false;
+}
+
+class AppendJSArrayCodeStubAssembler : public CodeStubAssembler {
+ public:
+ AppendJSArrayCodeStubAssembler(compiler::CodeAssemblerState* state,
+ ElementsKind kind)
+ : CodeStubAssembler(state), kind_(kind) {}
+
+ void TestAppendJSArrayImpl(Isolate* isolate, CodeAssemblerTester* tester,
+ Object* o1, Object* o2, Object* o3, Object* o4,
+ int initial_size, int result_size) {
+ typedef CodeAssemblerVariable Variable;
+ typedef CodeAssemblerLabel Label;
+ Handle<JSArray> array = isolate->factory()->NewJSArray(
+ kind_, 2, initial_size, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
+ JSObject::SetElement(isolate, array, 0,
+ Handle<Smi>(Smi::FromInt(1), isolate), SLOPPY)
+ .Check();
+ JSObject::SetElement(isolate, array, 1,
+ Handle<Smi>(Smi::FromInt(2), isolate), SLOPPY)
+ .Check();
+ CodeStubArguments args(this, Int32Constant(kNumParams));
+ Variable arg_index(this, MachineType::PointerRepresentation());
+ Label bailout(this);
+ arg_index.Bind(IntPtrConstant(0));
+ Node* length = BuildAppendJSArray(
+ kind_, HeapConstant(Handle<HeapObject>(isolate->context(), isolate)),
+ HeapConstant(array), args, arg_index, &bailout);
+ Return(length);
+
+ Bind(&bailout);
+ Return(SmiTag(IntPtrAdd(arg_index.value(), IntPtrConstant(2))));
+
+ Handle<Code> code = tester->GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+
+ Handle<Object> result =
+ ft.Call(Handle<Object>(o1, isolate), Handle<Object>(o2, isolate),
+ Handle<Object>(o3, isolate), Handle<Object>(o4, isolate))
+ .ToHandleChecked();
+
+ CHECK_EQ(kind_, array->GetElementsKind());
+ CHECK_EQ(result_size, Handle<Smi>::cast(result)->value());
+ CHECK_EQ(result_size, Smi::cast(array->length())->value());
+ Object* obj = *JSObject::GetElement(isolate, array, 2).ToHandleChecked();
+ CHECK_EQ(result_size < 3 ? isolate->heap()->undefined_value() : o1, obj);
+ obj = *JSObject::GetElement(isolate, array, 3).ToHandleChecked();
+ CHECK_EQ(result_size < 4 ? isolate->heap()->undefined_value() : o2, obj);
+ obj = *JSObject::GetElement(isolate, array, 4).ToHandleChecked();
+ CHECK_EQ(result_size < 5 ? isolate->heap()->undefined_value() : o3, obj);
+ obj = *JSObject::GetElement(isolate, array, 5).ToHandleChecked();
+ CHECK_EQ(result_size < 6 ? isolate->heap()->undefined_value() : o4, obj);
+ }
+
+ static void TestAppendJSArray(Isolate* isolate, ElementsKind kind, Object* o1,
+ Object* o2, Object* o3, Object* o4,
+ int initial_size, int result_size) {
+ CodeAssemblerTester data(isolate, kNumParams);
+ AppendJSArrayCodeStubAssembler m(data.state(), kind);
+ m.TestAppendJSArrayImpl(isolate, &data, o1, o2, o3, o4, initial_size,
+ result_size);
+ }
+
+ private:
+ static const int kNumParams = 4;
+ ElementsKind kind_;
+};
+
+TEST(BuildAppendJSArrayFastElement) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), Smi::FromInt(5),
+ Smi::FromInt(6), 6, 6);
+}
+
+TEST(BuildAppendJSArrayFastElementGrow) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), Smi::FromInt(5),
+ Smi::FromInt(6), 2, 6);
+}
+
+TEST(BuildAppendJSArrayFastSmiElement) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ Smi::FromInt(5), Smi::FromInt(6), 6, 6);
+}
+
+TEST(BuildAppendJSArrayFastSmiElementGrow) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ Smi::FromInt(5), Smi::FromInt(6), 2, 6);
+}
+
+TEST(BuildAppendJSArrayFastSmiElementObject) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ isolate->heap()->undefined_value(), Smi::FromInt(6), 6, 4);
+}
+
+TEST(BuildAppendJSArrayFastSmiElementObjectGrow) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ isolate->heap()->undefined_value(), Smi::FromInt(6), 2, 4);
+}
+
+TEST(BuildAppendJSArrayFastDoubleElements) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ Smi::FromInt(5), Smi::FromInt(6), 6, 6);
+}
+
+TEST(BuildAppendJSArrayFastDoubleElementsGrow) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ Smi::FromInt(5), Smi::FromInt(6), 2, 6);
+}
+
+TEST(BuildAppendJSArrayFastDoubleElementsObject) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ AppendJSArrayCodeStubAssembler::TestAppendJSArray(
+ isolate, FAST_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4),
+ isolate->heap()->undefined_value(), Smi::FromInt(6), 6, 4);
+}
+
+namespace {
+
+template <typename Stub, typename... Args>
+void Recompile(Args... args) {
+ Stub stub(args...);
+ stub.DeleteStubFromCacheForTesting();
+ stub.GetCode();
+}
+
+} // namespace
+
+void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise,
+ v8::Local<v8::Value> parentPromise) {}
+
+TEST(IsPromiseHookEnabled) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+
+ m.Return(m.SelectBooleanConstant(m.IsPromiseHookEnabled()));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+
+ isolate->SetPromiseHook(CustomPromiseHook);
+ result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->true_value(), *result);
+
+ isolate->SetPromiseHook(nullptr);
+ result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+}
+
+TEST(AllocateAndInitJSPromise) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const promise = m.AllocateAndInitJSPromise(context);
+ m.Return(promise);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result->IsJSPromise());
+}
+
+TEST(AllocateAndSetJSPromise) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const promise = m.AllocateAndSetJSPromise(
+ context, m.SmiConstant(v8::Promise::kPending), m.SmiConstant(1));
+ m.Return(promise);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result->IsJSPromise());
+ Handle<JSPromise> js_promise = Handle<JSPromise>::cast(result);
+ CHECK_EQ(v8::Promise::kPending, js_promise->status());
+ CHECK_EQ(Smi::FromInt(1), js_promise->result());
+ CHECK(!js_promise->has_handler());
+}
+
+TEST(AllocatePromiseReactionJobInfo) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+ PromiseBuiltinsAssembler p(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const tasks = m.AllocateFixedArray(FAST_ELEMENTS, m.IntPtrConstant(1));
+ m.StoreFixedArrayElement(tasks, 0, m.UndefinedConstant());
+ Node* const deferred_promise =
+ m.AllocateFixedArray(FAST_ELEMENTS, m.IntPtrConstant(1));
+ m.StoreFixedArrayElement(deferred_promise, 0, m.UndefinedConstant());
+ Node* const info = m.AllocatePromiseReactionJobInfo(
+ m.SmiConstant(1), tasks, deferred_promise, m.UndefinedConstant(),
+ m.UndefinedConstant(), context);
+ m.Return(info);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result->IsPromiseReactionJobInfo());
+ Handle<PromiseReactionJobInfo> promise_info =
+ Handle<PromiseReactionJobInfo>::cast(result);
+ CHECK_EQ(Smi::FromInt(1), promise_info->value());
+ CHECK(promise_info->tasks()->IsFixedArray());
+ CHECK(promise_info->deferred_promise()->IsFixedArray());
+ CHECK(promise_info->deferred_on_resolve()->IsUndefined(isolate));
+ CHECK(promise_info->deferred_on_reject()->IsUndefined(isolate));
+ CHECK(promise_info->context()->IsContext());
+ CHECK_EQ(kDebugPromiseNoID, promise_info->debug_id());
+}
+
+TEST(AllocatePromiseResolveThenableJobInfo) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler p(data.state());
+
+ Node* const context = p.Parameter(kNumParams + 2);
+ Node* const native_context = p.LoadNativeContext(context);
+ Node* const thenable = p.AllocateAndInitJSPromise(context);
+ Node* const then_str = p.HeapConstant(isolate->factory()->then_string());
+ Callable getproperty_callable = CodeFactory::GetProperty(isolate);
+ Node* const then =
+ p.CallStub(getproperty_callable, context, thenable, then_str);
+ Node* resolve = nullptr;
+ Node* reject = nullptr;
+ std::tie(resolve, reject) = p.CreatePromiseResolvingFunctions(
+ thenable, p.FalseConstant(), native_context);
+
+ Node* const info = p.AllocatePromiseResolveThenableJobInfo(
+ thenable, then, resolve, reject, context);
+ p.Return(info);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result->IsPromiseResolveThenableJobInfo());
+ Handle<PromiseResolveThenableJobInfo> promise_info =
+ Handle<PromiseResolveThenableJobInfo>::cast(result);
+ CHECK(promise_info->thenable()->IsJSPromise());
+ CHECK(promise_info->then()->IsJSFunction());
+ CHECK(promise_info->resolve()->IsJSFunction());
+ CHECK(promise_info->reject()->IsJSFunction());
+ CHECK_EQ(kDebugPromiseNoID, promise_info->debug_id());
+ CHECK(promise_info->context()->IsContext());
+}
+
+TEST(IsSymbol) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+
+ Node* const symbol = m.Parameter(0);
+ m.Return(m.SelectBooleanConstant(m.IsSymbol(symbol)));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->NewSymbol()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->true_value(), *result);
+
+ result = ft.Call(isolate->factory()->empty_string()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+}
+
+TEST(IsPrivateSymbol) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+
+ Node* const symbol = m.Parameter(0);
+ m.Return(m.SelectBooleanConstant(m.IsPrivateSymbol(symbol)));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->NewSymbol()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+
+ result = ft.Call(isolate->factory()->empty_string()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+
+ result = ft.Call(isolate->factory()->NewPrivateSymbol()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->true_value(), *result);
+}
+
+TEST(PromiseHasHandler) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const promise =
+ m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
+ m.Return(m.SelectBooleanConstant(m.PromiseHasHandler(promise)));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK_EQ(isolate->heap()->false_value(), *result);
+}
+
+TEST(CreatePromiseResolvingFunctionsContext) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const native_context = m.LoadNativeContext(context);
+ Node* const promise =
+ m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
+ Node* const promise_context = m.CreatePromiseResolvingFunctionsContext(
+ promise, m.BooleanConstant(false), native_context);
+ m.Return(promise_context);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result->IsContext());
+ Handle<Context> context_js = Handle<Context>::cast(result);
+ CHECK_EQ(isolate->native_context()->closure(), context_js->closure());
+ CHECK_EQ(isolate->heap()->the_hole_value(), context_js->extension());
+ CHECK_EQ(*isolate->native_context(), context_js->native_context());
+ CHECK_EQ(Smi::FromInt(0),
+ context_js->get(PromiseBuiltinsAssembler::kAlreadyVisitedSlot));
+ CHECK(context_js->get(PromiseBuiltinsAssembler::kPromiseSlot)->IsJSPromise());
+ CHECK_EQ(isolate->heap()->false_value(),
+ context_js->get(PromiseBuiltinsAssembler::kDebugEventSlot));
+}
+
+TEST(CreatePromiseResolvingFunctions) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const native_context = m.LoadNativeContext(context);
+ Node* const promise =
+ m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
+ Node *resolve, *reject;
+ std::tie(resolve, reject) = m.CreatePromiseResolvingFunctions(
+ promise, m.BooleanConstant(false), native_context);
+ Node* const kSize = m.IntPtrConstant(2);
+ Node* const arr = m.AllocateFixedArray(FAST_ELEMENTS, kSize);
+ m.StoreFixedArrayElement(arr, 0, resolve);
+ m.StoreFixedArrayElement(arr, 1, reject);
+ m.Return(arr);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result_obj =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result_obj->IsFixedArray());
+ Handle<FixedArray> result_arr = Handle<FixedArray>::cast(result_obj);
+ CHECK(result_arr->get(0)->IsJSFunction());
+ 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();
+ 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());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const native_context = m.LoadNativeContext(context);
+ Node* const promise =
+ m.AllocateAndInitJSPromise(context, m.UndefinedConstant());
+ Node* promise_context = m.CreatePromiseResolvingFunctionsContext(
+ promise, m.BooleanConstant(false), native_context);
+ Node* resolve_info =
+ m.LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN);
+ Node* const map = m.LoadContextElement(
+ native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX);
+ Node* const resolve =
+ m.AllocateFunctionWithMapAndContext(map, resolve_info, promise_context);
+ m.Return(resolve);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result_obj =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result_obj->IsJSFunction());
+ Handle<JSFunction> fun = Handle<JSFunction>::cast(result_obj);
+ CHECK_EQ(isolate->heap()->empty_fixed_array(), fun->properties());
+ CHECK_EQ(isolate->heap()->empty_fixed_array(), fun->elements());
+ CHECK_EQ(isolate->heap()->empty_literals_array(), fun->literals());
+ CHECK_EQ(isolate->heap()->the_hole_value(), fun->prototype_or_initial_map());
+ CHECK_EQ(*isolate->promise_resolve_shared_fun(), fun->shared());
+ CHECK_EQ(isolate->promise_resolve_shared_fun()->code(), fun->code());
+ CHECK_EQ(isolate->heap()->undefined_value(), fun->next_function_link());
+}
+
+TEST(CreatePromiseGetCapabilitiesExecutorContext) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const native_context = m.LoadNativeContext(context);
+
+ Node* const map = m.LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex);
+ Node* const capability = m.AllocateJSObjectFromMap(map);
+ m.StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kPromiseOffset, m.UndefinedConstant());
+ m.StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kResolveOffset, m.UndefinedConstant());
+ m.StoreObjectFieldNoWriteBarrier(
+ capability, JSPromiseCapability::kRejectOffset, m.UndefinedConstant());
+ Node* const executor_context =
+ m.CreatePromiseGetCapabilitiesExecutorContext(capability, native_context);
+ m.Return(executor_context);
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+
+ FunctionTester ft(code, kNumParams);
+ Handle<Object> result_obj =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result_obj->IsContext());
+ Handle<Context> context_js = Handle<Context>::cast(result_obj);
+ CHECK_EQ(PromiseBuiltinsAssembler::kCapabilitiesContextLength,
+ context_js->length());
+ CHECK_EQ(isolate->native_context()->closure(), context_js->closure());
+ CHECK_EQ(isolate->heap()->the_hole_value(), context_js->extension());
+ CHECK_EQ(*isolate->native_context(), context_js->native_context());
+ CHECK(context_js->get(PromiseBuiltinsAssembler::kCapabilitySlot)
+ ->IsJSPromiseCapability());
+}
+
+TEST(NewPromiseCapability) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+
+ { // Builtin Promise
+ const int kNumParams = 1;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+ Node* const native_context = m.LoadNativeContext(context);
+ Node* const promise_constructor =
+ m.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX);
+
+ Node* const capability =
+ m.NewPromiseCapability(context, promise_constructor);
+ m.Return(capability);
+
+ Handle<Code> code = data.GenerateCode();
+ FunctionTester ft(code, kNumParams);
+
+ Handle<Object> result_obj =
+ ft.Call(isolate->factory()->undefined_value()).ToHandleChecked();
+ CHECK(result_obj->IsJSPromiseCapability());
+ Handle<JSPromiseCapability> result =
+ Handle<JSPromiseCapability>::cast(result_obj);
+
+ CHECK(result->promise()->IsJSPromise());
+ CHECK(result->resolve()->IsJSFunction());
+ CHECK(result->reject()->IsJSFunction());
+ CHECK_EQ(isolate->native_context()->promise_resolve_shared_fun(),
+ JSFunction::cast(result->resolve())->shared());
+ CHECK_EQ(isolate->native_context()->promise_reject_shared_fun(),
+ JSFunction::cast(result->reject())->shared());
+
+ Handle<JSFunction> callbacks[] = {
+ handle(JSFunction::cast(result->resolve())),
+ handle(JSFunction::cast(result->reject()))};
+
+ for (auto&& callback : callbacks) {
+ Handle<Context> context(Context::cast(callback->context()));
+ CHECK_EQ(isolate->native_context()->closure(), context->closure());
+ CHECK_EQ(isolate->heap()->the_hole_value(), context->extension());
+ CHECK_EQ(*isolate->native_context(), context->native_context());
+ CHECK_EQ(PromiseBuiltinsAssembler::kPromiseContextLength,
+ context->length());
+ CHECK_EQ(context->get(PromiseBuiltinsAssembler::kPromiseSlot),
+ result->promise());
+ }
+ }
+
+ { // Custom Promise
+ const int kNumParams = 2;
+ CodeAssemblerTester data(isolate, kNumParams);
+ PromiseBuiltinsAssembler m(data.state());
+
+ Node* const context = m.Parameter(kNumParams + 2);
+
+ Node* const constructor = m.Parameter(1);
+ Node* const capability = m.NewPromiseCapability(context, constructor);
+ m.Return(capability);
+
+ Handle<Code> code = data.GenerateCode();
+ FunctionTester ft(code, kNumParams);
+
+ Handle<JSFunction> constructor_fn =
+ Handle<JSFunction>::cast(v8::Utils::OpenHandle(*CompileRun(
+ "(function FakePromise(executor) {"
+ " var self = this;"
+ " function resolve(value) { self.resolvedValue = value; }"
+ " function reject(reason) { self.rejectedReason = reason; }"
+ " executor(resolve, reject);"
+ "})")));
+
+ Handle<Object> result_obj =
+ ft.Call(isolate->factory()->undefined_value(), constructor_fn)
+ .ToHandleChecked();
+ CHECK(result_obj->IsJSPromiseCapability());
+ Handle<JSPromiseCapability> result =
+ Handle<JSPromiseCapability>::cast(result_obj);
+
+ CHECK(result->promise()->IsJSObject());
+ Handle<JSObject> promise(JSObject::cast(result->promise()));
+ CHECK_EQ(constructor_fn->prototype_or_initial_map(), promise->map());
+ CHECK(result->resolve()->IsJSFunction());
+ CHECK(result->reject()->IsJSFunction());
+
+ Handle<String> resolved_str =
+ isolate->factory()->NewStringFromAsciiChecked("resolvedStr");
+ Handle<String> rejected_str =
+ isolate->factory()->NewStringFromAsciiChecked("rejectedStr");
+
+ Handle<Object> argv1[] = {resolved_str};
+ Handle<Object> ret =
+ Execution::Call(isolate, handle(result->resolve(), isolate),
+ isolate->factory()->undefined_value(), 1, argv1)
+ .ToHandleChecked();
+
+ Handle<Object> prop1 =
+ JSReceiver::GetProperty(isolate, promise, "resolvedValue")
+ .ToHandleChecked();
+ CHECK_EQ(*resolved_str, *prop1);
+
+ Handle<Object> argv2[] = {rejected_str};
+ ret = Execution::Call(isolate, handle(result->reject(), isolate),
+ isolate->factory()->undefined_value(), 1, argv2)
+ .ToHandleChecked();
+ Handle<Object> prop2 =
+ JSReceiver::GetProperty(isolate, promise, "rejectedReason")
+ .ToHandleChecked();
+ CHECK_EQ(*rejected_str, *prop2);
+ }
+}
+
+TEST(DirectMemoryTest8BitWord32Immediate) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ typedef CodeAssemblerLabel Label;
+
+ const int kNumParams = 0;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+ int8_t buffer[] = {1, 2, 4, 8, 17, 33, 65, 127};
+ const int element_count = 8;
+ Label bad(&m);
+
+ Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
+ for (size_t i = 0; i < element_count; ++i) {
+ for (size_t j = 0; j < element_count; ++j) {
+ Node* loaded = m.LoadBufferObject(buffer_node, static_cast<int>(i),
+ MachineType::Uint8());
+ Node* masked = m.Word32And(loaded, m.Int32Constant(buffer[j]));
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+ }
+ }
+
+ m.Return(m.SmiConstant(1));
+
+ m.Bind(&bad);
+ m.Return(m.SmiConstant(0));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+ FunctionTester ft(code, kNumParams);
+ CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value());
+}
+
+TEST(DirectMemoryTest16BitWord32Immediate) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ typedef CodeAssemblerLabel Label;
+
+ const int kNumParams = 0;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+ int16_t buffer[] = {156, 2234, 4544, 8444, 1723, 3888, 658, 1278};
+ const int element_count = 8;
+ Label bad(&m);
+
+ Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
+ for (size_t i = 0; i < element_count; ++i) {
+ for (size_t j = 0; j < element_count; ++j) {
+ Node* loaded =
+ m.LoadBufferObject(buffer_node, static_cast<int>(i * sizeof(int16_t)),
+ MachineType::Uint16());
+ Node* masked = m.Word32And(loaded, m.Int32Constant(buffer[j]));
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+ }
+ }
+
+ m.Return(m.SmiConstant(1));
+
+ m.Bind(&bad);
+ m.Return(m.SmiConstant(0));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+ FunctionTester ft(code, kNumParams);
+ CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value());
+}
+
+TEST(DirectMemoryTest8BitWord32) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ typedef CodeAssemblerLabel Label;
+
+ const int kNumParams = 0;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+ int8_t buffer[] = {1, 2, 4, 8, 17, 33, 65, 127, 67, 38};
+ const int element_count = 10;
+ Label bad(&m);
+ Node* constants[element_count];
+
+ Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
+ for (size_t i = 0; i < element_count; ++i) {
+ constants[i] = m.LoadBufferObject(buffer_node, static_cast<int>(i),
+ MachineType::Uint8());
+ }
+
+ for (size_t i = 0; i < element_count; ++i) {
+ for (size_t j = 0; j < element_count; ++j) {
+ Node* loaded = m.LoadBufferObject(buffer_node, static_cast<int>(i),
+ MachineType::Uint8());
+ Node* masked = m.Word32And(loaded, constants[j]);
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+
+ masked = m.Word32And(constants[i], constants[j]);
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+ }
+ }
+
+ m.Return(m.SmiConstant(1));
+
+ m.Bind(&bad);
+ m.Return(m.SmiConstant(0));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+ FunctionTester ft(code, kNumParams);
+ CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value());
+}
+
+TEST(DirectMemoryTest16BitWord32) {
+ Isolate* isolate(CcTest::InitIsolateOnce());
+ typedef CodeAssemblerLabel Label;
+
+ const int kNumParams = 0;
+ CodeAssemblerTester data(isolate, kNumParams);
+ CodeStubAssembler m(data.state());
+ int16_t buffer[] = {1, 2, 4, 8, 12345, 33, 65, 255, 67, 3823};
+ const int element_count = 10;
+ Label bad(&m);
+ Node* constants[element_count];
+
+ Node* buffer_node1 = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
+ for (size_t i = 0; i < element_count; ++i) {
+ constants[i] =
+ m.LoadBufferObject(buffer_node1, static_cast<int>(i * sizeof(int16_t)),
+ MachineType::Uint16());
+ }
+ Node* buffer_node2 = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer));
+
+ for (size_t i = 0; i < element_count; ++i) {
+ for (size_t j = 0; j < element_count; ++j) {
+ Node* loaded = m.LoadBufferObject(buffer_node1,
+ static_cast<int>(i * sizeof(int16_t)),
+ MachineType::Uint16());
+ Node* masked = m.Word32And(loaded, constants[j]);
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+
+ // Force a memory access relative to a high-number register.
+ loaded = m.LoadBufferObject(buffer_node2,
+ static_cast<int>(i * sizeof(int16_t)),
+ MachineType::Uint16());
+ masked = m.Word32And(loaded, constants[j]);
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+
+ masked = m.Word32And(constants[i], constants[j]);
+ if ((buffer[j] & buffer[i]) != 0) {
+ m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad);
+ } else {
+ m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad);
+ }
+ }
+ }
+
+ m.Return(m.SmiConstant(1));
+
+ m.Bind(&bad);
+ m.Return(m.SmiConstant(0));
+
+ Handle<Code> code = data.GenerateCode();
+ CHECK(!code.is_null());
+ FunctionTester ft(code, kNumParams);
+ CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value());
+}
+
} // namespace internal
} // namespace v8