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 |