Commit b5925c0a authored by ishell's avatar ishell Committed by Commit bot

[stubs] Enable machine graph verification for CodeStubAssembler and friends by...

[stubs] Enable machine graph verification for CodeStubAssembler and friends by default in debug mode.

BUG=

Review-Url: https://codereview.chromium.org/2570213002
Cr-Commit-Position: refs/heads/master@{#41715}
parent ae741d04
......@@ -89,8 +89,7 @@ Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
compiler::CodeAssemblerState state(isolate, &zone, argc_with_recv, flags,
name);
generator(&state);
Handle<Code> code =
compiler::CodeAssembler::GenerateCode(&state, FLAG_csa_verify);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
......@@ -109,8 +108,7 @@ Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
DCHECK_LE(0, descriptor.GetRegisterParameterCount());
compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name);
generator(&state);
Handle<Code> code =
compiler::CodeAssembler::GenerateCode(&state, FLAG_csa_verify);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name);
return *code;
}
......
......@@ -286,7 +286,7 @@ Handle<Code> HydrogenCodeStub::GenerateRuntimeTailCall(
UNIMPLEMENTED();
break;
}
return compiler::CodeAssembler::GenerateCode(&state, FLAG_csa_verify);
return compiler::CodeAssembler::GenerateCode(&state);
}
template <class Stub>
......
......@@ -437,10 +437,7 @@ Handle<Code> TurboFanCodeStub::GenerateCode() {
compiler::CodeAssemblerState state(isolate(), &zone, descriptor,
GetCodeFlags(), name);
GenerateAssembly(&state);
// TODO(ishell): enable verification once all issues are fixed.
// Enable verification only in mksnapshot.
bool verify_graph = FLAG_csa_verify && FLAG_startup_blob != nullptr;
return compiler::CodeAssembler::GenerateCode(&state, verify_graph);
return compiler::CodeAssembler::GenerateCode(&state);
}
#define ACCESSOR_ASSEMBLER(Name) \
......
......@@ -70,17 +70,14 @@ void CodeAssembler::CallPrologue() {}
void CodeAssembler::CallEpilogue() {}
// static
Handle<Code> CodeAssembler::GenerateCode(CodeAssemblerState* state,
bool verify_graph) {
// TODO(ishell): Remove verify_graph parameter and always enable the
// verification once all the issues are fixed.
Handle<Code> CodeAssembler::GenerateCode(CodeAssemblerState* state) {
DCHECK(!state->code_generated_);
RawMachineAssembler* rasm = state->raw_assembler_.get();
Schedule* schedule = rasm->Export();
Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
rasm->isolate(), rasm->call_descriptor(), rasm->graph(), schedule,
state->flags_, state->name_, verify_graph);
state->flags_, state->name_);
state->code_generated_ = true;
return code;
......
......@@ -190,8 +190,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
virtual ~CodeAssembler();
static Handle<Code> GenerateCode(CodeAssemblerState* state,
bool verify_graph = false);
static Handle<Code> GenerateCode(CodeAssemblerState* state);
bool Is64() const;
bool IsFloat64RoundUpSupported() const;
......
......@@ -1614,14 +1614,11 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
return ScheduleAndSelectInstructions(linkage, true);
}
// TODO(ishell): Remove verify_graph parameter and always enable the
// verification once all the issues are fixed.
Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate,
CallDescriptor* call_descriptor,
Graph* graph, Schedule* schedule,
Code::Flags flags,
const char* debug_name,
bool verify_graph) {
const char* debug_name) {
CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), flags);
if (isolate->serializer_enabled()) info.PrepareForSerializing();
......@@ -1629,7 +1626,7 @@ Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate,
ZoneStats zone_stats(isolate->allocator());
SourcePositionTable source_positions(graph);
PipelineData data(&zone_stats, &info, graph, schedule, &source_positions);
data.set_verify_graph(verify_graph);
data.set_verify_graph(FLAG_csa_verify);
std::unique_ptr<PipelineStatistics> pipeline_statistics;
if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) {
pipeline_statistics.reset(new PipelineStatistics(&info, &zone_stats));
......
......@@ -49,8 +49,7 @@ class Pipeline : public AllStatic {
CallDescriptor* call_descriptor,
Graph* graph, Schedule* schedule,
Code::Flags flags,
const char* debug_name,
bool verify_graph);
const char* debug_name);
// Run the entire pipeline and generate a handle to a code object suitable for
// testing.
......
......@@ -240,8 +240,8 @@ void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id,
MaybeHandle<Code> FastAccessorAssembler::Build() {
CHECK_EQ(kBuilding, state_);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(
assembler_state_.get(), FLAG_csa_verify);
Handle<Code> code =
compiler::CodeAssembler::GenerateCode(assembler_state_.get());
state_ = !code.is_null() ? kBuilt : kError;
Clear();
return code;
......
......@@ -104,11 +104,7 @@ void Interpreter::InstallBytecodeHandler(Zone* zone, Bytecode bytecode,
Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode));
InterpreterAssembler assembler(&state, bytecode, operand_scale);
(this->*generator)(&assembler);
// TODO(ishell): enable verification once all issues are fixed.
// Enable verification only in mksnapshot.
bool verify_graph = FLAG_csa_verify && FLAG_startup_blob != nullptr;
Handle<Code> code =
compiler::CodeAssembler::GenerateCode(&state, verify_graph);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
size_t index = GetDispatchTableIndex(bytecode, operand_scale);
dispatch_table_[index] = code->entry();
TraceCodegen(code);
......
......@@ -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
......@@ -36,7 +36,7 @@ void TestStubCacheOffsetCalculation(StubCache::Table table) {
CHECK_EQ(StubCache::kSecondary, table);
result = m.StubCacheSecondaryOffsetForTesting(name, primary_offset);
}
m.Return(m.SmiFromWord32(result));
m.Return(m.SmiTag(result));
}
Handle<Code> code = data.GenerateCode();
......
This diff is collapsed.
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