| Index: test/cctest/compiler/test-code-assembler.cc
|
| diff --git a/test/cctest/compiler/test-code-assembler.cc b/test/cctest/compiler/test-code-assembler.cc
|
| index 7d376edb5b7f162680f78c13f9eec8e4c3fc7fb7..90fdc2b7ae37b97f61cecd0a0af624285f09741f 100644
|
| --- a/test/cctest/compiler/test-code-assembler.cc
|
| +++ b/test/cctest/compiler/test-code-assembler.cc
|
| @@ -27,11 +27,21 @@ Node* UndefinedConstant(CodeAssembler& m) {
|
| return m.LoadRoot(Heap::kUndefinedValueRootIndex);
|
| }
|
|
|
| +Node* SmiFromWord32(CodeAssembler& m, Node* value) {
|
| + value = m.ChangeInt32ToIntPtr(value);
|
| + return m.BitcastWordToTaggedSigned(
|
| + m.WordShl(value, kSmiShiftSize + kSmiTagSize));
|
| +}
|
| +
|
| Node* LoadObjectField(CodeAssembler& m, Node* object, int offset,
|
| MachineType rep = MachineType::AnyTagged()) {
|
| return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag));
|
| }
|
|
|
| +Node* LoadMap(CodeAssembler& m, Node* object) {
|
| + return LoadObjectField(m, object, JSObject::kMapOffset);
|
| +}
|
| +
|
| } // namespace
|
|
|
| TEST(SimpleSmiReturn) {
|
| @@ -50,7 +60,8 @@ TEST(SimpleIntPtrReturn) {
|
| CodeAssemblerTester data(isolate);
|
| CodeAssembler m(data.state());
|
| int test;
|
| - m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
|
| + m.Return(m.BitcastWordToTagged(
|
| + m.IntPtrConstant(reinterpret_cast<intptr_t>(&test))));
|
| Handle<Code> code = data.GenerateCode();
|
| FunctionTester ft(code);
|
| MaybeHandle<Object> result = ft.Call();
|
| @@ -382,7 +393,6 @@ TEST(TestToConstant) {
|
| }
|
|
|
| TEST(DeferredCodePhiHints) {
|
| - typedef compiler::Node Node;
|
| typedef CodeAssemblerLabel Label;
|
| typedef CodeAssemblerVariable Variable;
|
| Isolate* isolate(CcTest::InitIsolateOnce());
|
| @@ -394,11 +404,11 @@ TEST(DeferredCodePhiHints) {
|
| {
|
| Variable var_object(&m, MachineRepresentation::kTagged);
|
| Label loop(&m, &var_object);
|
| - var_object.Bind(m.IntPtrConstant(0));
|
| + var_object.Bind(m.SmiConstant(0));
|
| m.Goto(&loop);
|
| m.Bind(&loop);
|
| {
|
| - Node* map = LoadObjectField(m, var_object.value(), JSObject::kMapOffset);
|
| + Node* map = LoadMap(m, var_object.value());
|
| var_object.Bind(map);
|
| m.Goto(&loop);
|
| }
|
| @@ -435,6 +445,135 @@ TEST(TestOutOfScopeVariable) {
|
| CHECK(!data.GenerateCode().is_null());
|
| }
|
|
|
| +TEST(GotoIfException) {
|
| + typedef CodeAssemblerLabel Label;
|
| + typedef CodeAssemblerVariable Variable;
|
| + Isolate* isolate(CcTest::InitIsolateOnce());
|
| +
|
| + const int kNumParams = 1;
|
| + CodeAssemblerTester data(isolate, kNumParams);
|
| + CodeAssembler m(data.state());
|
| +
|
| + 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 = data.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 CodeAssemblerLabel Label;
|
| + typedef CodeAssemblerVariable Variable;
|
| + Isolate* isolate(CcTest::InitIsolateOnce());
|
| +
|
| + const int kNumParams = 4; // receiver, first, second, third
|
| + CodeAssemblerTester data(isolate, kNumParams);
|
| + CodeAssembler m(data.state());
|
| +
|
| + 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(UndefinedConstant(m));
|
| + string = m.CallStub(to_string, context, second_value);
|
| + m.GotoIfException(string, &exception_handler2, &error);
|
| + m.Return(SmiFromWord32(m, return_value.value()));
|
| +
|
| + // try { ToString(param3); return 7 & ~2; } catch (e) { return e; }
|
| + m.Bind(&exception_handler2);
|
| + // Return returnValue & ~2
|
| + error.Bind(UndefinedConstant(m));
|
| + string = m.CallStub(to_string, context, third_value);
|
| + m.GotoIfException(string, &exception_handler3, &error);
|
| + m.Return(SmiFromWord32(
|
| + m, m.Word32And(return_value.value(),
|
| + m.Word32Xor(m.Int32Constant(2), m.Int32Constant(-1)))));
|
| +
|
| + m.Bind(&exception_handler3);
|
| + m.Return(error.value());
|
| +
|
| + Handle<Code> code = data.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()));
|
| +}
|
| +
|
| } // namespace compiler
|
| } // namespace internal
|
| } // namespace v8
|
|
|