[wasm] OOB traps: build protected instruction list during codegen
During codegen, we build a list mapping protected instructions to their associated landing pads. This will ultimately by used by the signal handler to recover from out of bounds faults and throw a JS exception. This is mostly pulled from my larger in-progress CL at https://codereview.chromium.org/2371833007/. BUG= https://bugs.chromium.org/p/v8/issues/detail?id=5277 Review-Url: https://codereview.chromium.org/2500443004 Cr-Commit-Position: refs/heads/master@{#41400}
This commit is contained in:
parent
9b20a7b7a3
commit
bf35d15e52
1
BUILD.gn
1
BUILD.gn
@ -1700,6 +1700,7 @@ v8_source_set("v8_base") {
|
||||
"src/transitions-inl.h",
|
||||
"src/transitions.cc",
|
||||
"src/transitions.h",
|
||||
"src/trap-handler/trap-handler.h",
|
||||
"src/type-feedback-vector-inl.h",
|
||||
"src/type-feedback-vector.cc",
|
||||
"src/type-feedback-vector.h",
|
||||
|
@ -33,8 +33,10 @@ class CodeGenerator::JumpTable final : public ZoneObject {
|
||||
size_t const target_count_;
|
||||
};
|
||||
|
||||
CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
|
||||
InstructionSequence* code, CompilationInfo* info)
|
||||
CodeGenerator::CodeGenerator(
|
||||
Frame* frame, Linkage* linkage, InstructionSequence* code,
|
||||
CompilationInfo* info,
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions)
|
||||
: frame_access_state_(nullptr),
|
||||
linkage_(linkage),
|
||||
code_(code),
|
||||
@ -57,7 +59,8 @@ CodeGenerator::CodeGenerator(Frame* frame, Linkage* linkage,
|
||||
ools_(nullptr),
|
||||
osr_pc_offset_(-1),
|
||||
source_position_table_builder_(code->zone(),
|
||||
info->SourcePositionRecordingMode()) {
|
||||
info->SourcePositionRecordingMode()),
|
||||
protected_instructions_(protected_instructions) {
|
||||
for (int i = 0; i < code->InstructionBlockCount(); ++i) {
|
||||
new (&labels_[i]) Label;
|
||||
}
|
||||
@ -71,6 +74,15 @@ void CodeGenerator::CreateFrameAccessState(Frame* frame) {
|
||||
frame_access_state_ = new (code()->zone()) FrameAccessState(frame);
|
||||
}
|
||||
|
||||
void CodeGenerator::AddProtectedInstruction(int instr_offset,
|
||||
int landing_offset) {
|
||||
if (protected_instructions_ != nullptr) {
|
||||
trap_handler::ProtectedInstructionData data = {instr_offset,
|
||||
landing_offset};
|
||||
protected_instructions_->emplace_back(data);
|
||||
}
|
||||
}
|
||||
|
||||
Handle<Code> CodeGenerator::GenerateCode() {
|
||||
CompilationInfo* info = this->info();
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/macro-assembler.h"
|
||||
#include "src/safepoint-table.h"
|
||||
#include "src/source-position-table.h"
|
||||
#include "src/trap-handler/trap-handler.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -52,7 +53,9 @@ class InstructionOperandIterator {
|
||||
class CodeGenerator final : public GapResolver::Assembler {
|
||||
public:
|
||||
explicit CodeGenerator(Frame* frame, Linkage* linkage,
|
||||
InstructionSequence* code, CompilationInfo* info);
|
||||
InstructionSequence* code, CompilationInfo* info,
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>*
|
||||
protected_instructions = nullptr);
|
||||
|
||||
// Generate native code.
|
||||
Handle<Code> GenerateCode();
|
||||
@ -65,6 +68,8 @@ class CodeGenerator final : public GapResolver::Assembler {
|
||||
|
||||
Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
|
||||
|
||||
void AddProtectedInstruction(int instr_offset, int landing_offset);
|
||||
|
||||
private:
|
||||
MacroAssembler* masm() { return &masm_; }
|
||||
GapResolver* resolver() { return &resolver_; }
|
||||
@ -280,6 +285,7 @@ class CodeGenerator final : public GapResolver::Assembler {
|
||||
OutOfLineCode* ools_;
|
||||
int osr_pc_offset_;
|
||||
SourcePositionTableBuilder source_position_table_builder_;
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "src/ostreams.h"
|
||||
#include "src/parsing/parse-info.h"
|
||||
#include "src/register-configuration.h"
|
||||
#include "src/trap-handler/trap-handler.h"
|
||||
#include "src/type-info.h"
|
||||
#include "src/utils.h"
|
||||
|
||||
@ -114,7 +115,9 @@ class PipelineData {
|
||||
|
||||
// For WASM compile entry point.
|
||||
PipelineData(ZoneStats* zone_stats, CompilationInfo* info, JSGraph* jsgraph,
|
||||
SourcePositionTable* source_positions)
|
||||
SourcePositionTable* source_positions,
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>*
|
||||
protected_instructions)
|
||||
: isolate_(info->isolate()),
|
||||
info_(info),
|
||||
debug_name_(info_->GetDebugName()),
|
||||
@ -129,7 +132,8 @@ class PipelineData {
|
||||
instruction_zone_scope_(zone_stats_, ZONE_NAME),
|
||||
instruction_zone_(instruction_zone_scope_.zone()),
|
||||
register_allocation_zone_scope_(zone_stats_, ZONE_NAME),
|
||||
register_allocation_zone_(register_allocation_zone_scope_.zone()) {}
|
||||
register_allocation_zone_(register_allocation_zone_scope_.zone()),
|
||||
protected_instructions_(protected_instructions) {}
|
||||
|
||||
// For machine graph testing entry point.
|
||||
PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Graph* graph,
|
||||
@ -230,6 +234,11 @@ class PipelineData {
|
||||
source_position_output_ = source_position_output;
|
||||
}
|
||||
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions()
|
||||
const {
|
||||
return protected_instructions_;
|
||||
}
|
||||
|
||||
void DeleteGraphZone() {
|
||||
if (graph_zone_ == nullptr) return;
|
||||
graph_zone_scope_.Destroy();
|
||||
@ -350,6 +359,9 @@ class PipelineData {
|
||||
// Source position output for --trace-turbo.
|
||||
std::string source_position_output_;
|
||||
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions_ =
|
||||
nullptr;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PipelineData);
|
||||
};
|
||||
|
||||
@ -609,13 +621,14 @@ PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() {
|
||||
|
||||
class PipelineWasmCompilationJob final : public CompilationJob {
|
||||
public:
|
||||
explicit PipelineWasmCompilationJob(CompilationInfo* info, JSGraph* jsgraph,
|
||||
CallDescriptor* descriptor,
|
||||
SourcePositionTable* source_positions)
|
||||
explicit PipelineWasmCompilationJob(
|
||||
CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor,
|
||||
SourcePositionTable* source_positions,
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>* protected_insts)
|
||||
: CompilationJob(info->isolate(), info, "TurboFan",
|
||||
State::kReadyToExecute),
|
||||
zone_stats_(info->isolate()->allocator()),
|
||||
data_(&zone_stats_, info, jsgraph, source_positions),
|
||||
data_(&zone_stats_, info, jsgraph, source_positions, protected_insts),
|
||||
pipeline_(&data_),
|
||||
linkage_(descriptor) {}
|
||||
|
||||
@ -1403,7 +1416,7 @@ struct GenerateCodePhase {
|
||||
|
||||
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
|
||||
CodeGenerator generator(data->frame(), linkage, data->sequence(),
|
||||
data->info());
|
||||
data->info(), data->protected_instructions());
|
||||
data->set_code(generator.GenerateCode());
|
||||
}
|
||||
};
|
||||
@ -1727,9 +1740,11 @@ CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function) {
|
||||
// static
|
||||
CompilationJob* Pipeline::NewWasmCompilationJob(
|
||||
CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor,
|
||||
SourcePositionTable* source_positions) {
|
||||
return new PipelineWasmCompilationJob(info, jsgraph, descriptor,
|
||||
source_positions);
|
||||
SourcePositionTable* source_positions,
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>*
|
||||
protected_instructions) {
|
||||
return new PipelineWasmCompilationJob(
|
||||
info, jsgraph, descriptor, source_positions, protected_instructions);
|
||||
}
|
||||
|
||||
bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
|
||||
|
@ -9,6 +9,7 @@
|
||||
// Do not include anything from src/compiler here!
|
||||
#include "src/globals.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/zone/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -17,6 +18,10 @@ class CompilationInfo;
|
||||
class CompilationJob;
|
||||
class RegisterConfiguration;
|
||||
|
||||
namespace trap_handler {
|
||||
struct ProtectedInstructionData;
|
||||
} // namespace trap_handler
|
||||
|
||||
namespace compiler {
|
||||
|
||||
class CallDescriptor;
|
||||
@ -34,7 +39,9 @@ class Pipeline : public AllStatic {
|
||||
// Returns a new compilation job for the WebAssembly compilation info.
|
||||
static CompilationJob* NewWasmCompilationJob(
|
||||
CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor,
|
||||
SourcePositionTable* source_positions);
|
||||
SourcePositionTable* source_positions,
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>*
|
||||
protected_instructions);
|
||||
|
||||
// Run the pipeline on a machine graph and generate code. The {schedule} must
|
||||
// be valid, hence the given {graph} does not need to be schedulable.
|
||||
|
@ -3411,7 +3411,8 @@ WasmCompilationUnit::WasmCompilationUnit(wasm::ErrorThrower* thrower,
|
||||
Code::ComputeFlags(Code::WASM_FUNCTION)),
|
||||
job_(),
|
||||
index_(index),
|
||||
ok_(true) {
|
||||
ok_(true),
|
||||
protected_instructions_(&compilation_zone_) {
|
||||
// Create and cache this node in the main thread.
|
||||
jsgraph_->CEntryStubConstant(1);
|
||||
}
|
||||
@ -3452,7 +3453,8 @@ void WasmCompilationUnit::ExecuteCompilation() {
|
||||
module_env_->GetI32WasmCallDescriptor(&compilation_zone_, descriptor);
|
||||
}
|
||||
job_.reset(Pipeline::NewWasmCompilationJob(&info_, jsgraph_, descriptor,
|
||||
source_positions));
|
||||
source_positions,
|
||||
&protected_instructions_));
|
||||
ok_ = job_->ExecuteJob() == CompilationJob::SUCCEEDED;
|
||||
// TODO(bradnelson): Improve histogram handling of size_t.
|
||||
// TODO(ahaas): The counters are not thread-safe at the moment.
|
||||
@ -3510,9 +3512,27 @@ Handle<Code> WasmCompilationUnit::FinishCompilation() {
|
||||
compile_ms);
|
||||
}
|
||||
|
||||
Handle<FixedArray> protected_instructions = PackProtectedInstructions();
|
||||
code->set_protected_instructions(*protected_instructions);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
Handle<FixedArray> WasmCompilationUnit::PackProtectedInstructions() const {
|
||||
const int num_instructions = static_cast<int>(protected_instructions_.size());
|
||||
Handle<FixedArray> fn_protected = isolate_->factory()->NewFixedArray(
|
||||
num_instructions * Code::kTrapDataSize, TENURED);
|
||||
for (unsigned i = 0; i < protected_instructions_.size(); ++i) {
|
||||
const trap_handler::ProtectedInstructionData& instruction =
|
||||
protected_instructions_[i];
|
||||
fn_protected->set(Code::kTrapDataSize * i + Code::kTrapCodeOffset,
|
||||
Smi::FromInt(instruction.instr_offset));
|
||||
fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset,
|
||||
Smi::FromInt(instruction.landing_offset));
|
||||
}
|
||||
return fn_protected;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -11,6 +11,8 @@
|
||||
// Do not include anything from src/compiler here!
|
||||
#include "src/compilation-info.h"
|
||||
#include "src/compiler.h"
|
||||
#include "src/trap-handler/trap-handler.h"
|
||||
#include "src/wasm/wasm-module.h"
|
||||
#include "src/wasm/wasm-opcodes.h"
|
||||
#include "src/wasm/wasm-result.h"
|
||||
#include "src/zone/zone.h"
|
||||
@ -58,13 +60,15 @@ class WasmCompilationUnit final {
|
||||
Isolate* isolate,
|
||||
wasm::ModuleBytesEnv* module_env,
|
||||
const wasm::WasmFunction* function) {
|
||||
WasmCompilationUnit unit(thrower, isolate, module_env, function, 0);
|
||||
WasmCompilationUnit unit(thrower, isolate, module_env, function,
|
||||
function->func_index);
|
||||
unit.ExecuteCompilation();
|
||||
return unit.FinishCompilation();
|
||||
}
|
||||
|
||||
private:
|
||||
SourcePositionTable* BuildGraphForWasmFunction(double* decode_ms);
|
||||
Handle<FixedArray> PackProtectedInstructions() const;
|
||||
|
||||
wasm::ErrorThrower* thrower_;
|
||||
Isolate* isolate_;
|
||||
@ -79,6 +83,9 @@ class WasmCompilationUnit final {
|
||||
uint32_t index_;
|
||||
wasm::Result<wasm::DecodeStruct*> graph_construction_result_;
|
||||
bool ok_;
|
||||
ZoneVector<trap_handler::ProtectedInstructionData>
|
||||
protected_instructions_; // Instructions that are protected by the signal
|
||||
// handler.
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WasmCompilationUnit);
|
||||
};
|
||||
|
@ -270,18 +270,21 @@ class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
|
||||
class WasmOutOfLineTrap final : public OutOfLineCode {
|
||||
public:
|
||||
WasmOutOfLineTrap(CodeGenerator* gen, Address pc, bool frame_elided,
|
||||
WasmOutOfLineTrap(CodeGenerator* gen, int pc, bool frame_elided,
|
||||
Register context, int32_t position)
|
||||
: OutOfLineCode(gen),
|
||||
gen_(gen),
|
||||
pc_(pc),
|
||||
frame_elided_(frame_elided),
|
||||
context_(context),
|
||||
position_(position) {}
|
||||
|
||||
// TODO(eholk): Refactor this method to take the code generator as a
|
||||
// parameter.
|
||||
void Generate() final {
|
||||
// TODO(eholk): record pc_ and the current pc in a table so that
|
||||
// the signal handler can find it.
|
||||
USE(pc_);
|
||||
int current_pc = __ pc_offset();
|
||||
|
||||
gen_->AddProtectedInstruction(pc_, current_pc);
|
||||
|
||||
if (frame_elided_) {
|
||||
__ EnterFrame(StackFrame::WASM);
|
||||
@ -296,7 +299,8 @@ class WasmOutOfLineTrap final : public OutOfLineCode {
|
||||
}
|
||||
|
||||
private:
|
||||
Address pc_;
|
||||
CodeGenerator* gen_;
|
||||
int pc_;
|
||||
bool frame_elided_;
|
||||
Register context_;
|
||||
int32_t position_;
|
||||
@ -304,7 +308,7 @@ class WasmOutOfLineTrap final : public OutOfLineCode {
|
||||
|
||||
void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen,
|
||||
InstructionCode opcode, X64OperandConverter& i,
|
||||
Address pc) {
|
||||
int pc) {
|
||||
X64MemoryProtection protection =
|
||||
static_cast<X64MemoryProtection>(MiscField::decode(opcode));
|
||||
if (protection == X64MemoryProtection::kProtected) {
|
||||
@ -1850,21 +1854,21 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
break;
|
||||
case kX64Movsxbl:
|
||||
ASSEMBLE_MOVX(movsxbl);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
break;
|
||||
case kX64Movzxbl:
|
||||
ASSEMBLE_MOVX(movzxbl);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
break;
|
||||
case kX64Movsxbq:
|
||||
ASSEMBLE_MOVX(movsxbq);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
case kX64Movzxbq:
|
||||
ASSEMBLE_MOVX(movzxbq);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
break;
|
||||
case kX64Movb: {
|
||||
@ -1875,26 +1879,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
} else {
|
||||
__ movb(operand, i.InputRegister(index));
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
}
|
||||
case kX64Movsxwl:
|
||||
ASSEMBLE_MOVX(movsxwl);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
break;
|
||||
case kX64Movzxwl:
|
||||
ASSEMBLE_MOVX(movzxwl);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
break;
|
||||
case kX64Movsxwq:
|
||||
ASSEMBLE_MOVX(movsxwq);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
case kX64Movzxwq:
|
||||
ASSEMBLE_MOVX(movzxwq);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
break;
|
||||
case kX64Movw: {
|
||||
@ -1905,7 +1909,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
} else {
|
||||
__ movw(operand, i.InputRegister(index));
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
}
|
||||
case kX64Movl:
|
||||
@ -1919,7 +1923,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
} else {
|
||||
__ movl(i.OutputRegister(), i.MemoryOperand());
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
__ AssertZeroExtended(i.OutputRegister());
|
||||
} else {
|
||||
size_t index = 0;
|
||||
@ -1929,12 +1933,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
} else {
|
||||
__ movl(operand, i.InputRegister(index));
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
}
|
||||
break;
|
||||
case kX64Movsxlq:
|
||||
ASSEMBLE_MOVX(movsxlq);
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
case kX64Movq:
|
||||
if (instr->HasOutput()) {
|
||||
@ -1948,7 +1952,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ movq(operand, i.InputRegister(index));
|
||||
}
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
case kX64Movss:
|
||||
if (instr->HasOutput()) {
|
||||
@ -1958,7 +1962,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
Operand operand = i.MemoryOperand(&index);
|
||||
__ movss(operand, i.InputDoubleRegister(index));
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
case kX64Movsd:
|
||||
if (instr->HasOutput()) {
|
||||
@ -1968,7 +1972,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
Operand operand = i.MemoryOperand(&index);
|
||||
__ Movsd(operand, i.InputDoubleRegister(index));
|
||||
}
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc());
|
||||
EmitOOLTrapIfNeeded(zone(), this, opcode, i, __ pc_offset());
|
||||
break;
|
||||
case kX64BitcastFI:
|
||||
if (instr->InputAt(0)->IsFPStackSlot()) {
|
||||
|
@ -179,8 +179,7 @@ class X64OperandGenerator final : public OperandGenerator {
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
ArchOpcode GetLoadOpcode(LoadRepresentation load_rep) {
|
||||
ArchOpcode GetLoadOpcode(LoadRepresentation load_rep, bool protect) {
|
||||
ArchOpcode opcode = kArchNop;
|
||||
switch (load_rep.representation()) {
|
||||
case MachineRepresentation::kFloat32:
|
||||
@ -252,7 +251,8 @@ void InstructionSelector::VisitLoad(Node* node) {
|
||||
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
|
||||
X64OperandGenerator g(this);
|
||||
|
||||
ArchOpcode opcode = GetLoadOpcode(load_rep);
|
||||
const bool protect = false;
|
||||
ArchOpcode opcode = GetLoadOpcode(load_rep, protect);
|
||||
InstructionOperand outputs[1];
|
||||
outputs[0] = g.DefineAsRegister(node);
|
||||
InstructionOperand inputs[3];
|
||||
@ -267,7 +267,8 @@ void InstructionSelector::VisitProtectedLoad(Node* node) {
|
||||
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
|
||||
X64OperandGenerator g(this);
|
||||
|
||||
ArchOpcode opcode = GetLoadOpcode(load_rep);
|
||||
const bool protect = true;
|
||||
ArchOpcode opcode = GetLoadOpcode(load_rep, protect);
|
||||
InstructionOperand outputs[1];
|
||||
outputs[0] = g.DefineAsRegister(node);
|
||||
InstructionOperand inputs[4];
|
||||
|
@ -6808,6 +6808,7 @@ ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
|
||||
ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
|
||||
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
|
||||
ACCESSORS(Code, source_position_table, ByteArray, kSourcePositionTableOffset)
|
||||
ACCESSORS(Code, protected_instructions, FixedArray, kProtectedInstructionOffset)
|
||||
ACCESSORS(Code, raw_type_feedback_info, Object, kTypeFeedbackInfoOffset)
|
||||
ACCESSORS(Code, next_code_link, Object, kNextCodeLinkOffset)
|
||||
|
||||
|
@ -5421,6 +5421,10 @@ class Code: public HeapObject {
|
||||
// [source_position_table]: ByteArray for the source positions table.
|
||||
DECL_ACCESSORS(source_position_table, ByteArray)
|
||||
|
||||
// [protected_instructions]: Fixed array containing protected instruction and
|
||||
// corresponding landing pad offsets.
|
||||
DECL_ACCESSORS(protected_instructions, FixedArray)
|
||||
|
||||
// [raw_type_feedback_info]: This field stores various things, depending on
|
||||
// the kind of the code object.
|
||||
// FUNCTION => type feedback information.
|
||||
@ -5800,7 +5804,12 @@ class Code: public HeapObject {
|
||||
static const int kConstantPoolOffset = kPrologueOffset + kIntSize;
|
||||
static const int kBuiltinIndexOffset =
|
||||
kConstantPoolOffset + kConstantPoolSize;
|
||||
static const int kHeaderPaddingStart = kBuiltinIndexOffset + kIntSize;
|
||||
static const int kProtectedInstructionOffset = kBuiltinIndexOffset + kIntSize;
|
||||
|
||||
enum TrapFields { kTrapCodeOffset, kTrapLandingOffset, kTrapDataSize };
|
||||
|
||||
static const int kHeaderPaddingStart =
|
||||
kProtectedInstructionOffset + kPointerSize;
|
||||
|
||||
// Add padding to align the instruction start following right after
|
||||
// the Code object header.
|
||||
|
26
src/trap-handler/trap-handler.h
Normal file
26
src/trap-handler/trap-handler.h
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_TRAP_HANDLER_H_
|
||||
#define V8_TRAP_HANDLER_H_
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace trap_handler {
|
||||
|
||||
struct ProtectedInstructionData {
|
||||
// The offset of this instruction from the start of its code object.
|
||||
int32_t instr_offset;
|
||||
|
||||
// The offset of the landing pad from the start of its code object.
|
||||
//
|
||||
// TODO(eholk): Using a single landing pad and store parameters here.
|
||||
int32_t landing_offset;
|
||||
};
|
||||
|
||||
} // namespace trap_handler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_TRAP_HANDLER_H_
|
@ -1238,6 +1238,7 @@
|
||||
'transitions-inl.h',
|
||||
'transitions.cc',
|
||||
'transitions.h',
|
||||
'trap-handler/trap-handler.h',
|
||||
'type-feedback-vector-inl.h',
|
||||
'type-feedback-vector.cc',
|
||||
'type-feedback-vector.h',
|
||||
|
@ -1260,6 +1260,38 @@ class WasmInstanceBuilder {
|
||||
FlushICache(isolate_, code_table);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Unpack and notify signal handler of protected instructions.
|
||||
//--------------------------------------------------------------------------
|
||||
{
|
||||
for (int i = 0; i < code_table->length(); ++i) {
|
||||
Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i);
|
||||
|
||||
if (code->kind() != Code::WASM_FUNCTION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FixedArray* protected_instructions = code->protected_instructions();
|
||||
|
||||
Zone zone(isolate_->allocator(), "Wasm Module");
|
||||
ZoneVector<trap_handler::ProtectedInstructionData> unpacked(&zone);
|
||||
for (int i = 0; i < protected_instructions->length();
|
||||
i += Code::kTrapDataSize) {
|
||||
trap_handler::ProtectedInstructionData data;
|
||||
data.instr_offset =
|
||||
protected_instructions
|
||||
->GetValueChecked<Smi>(isolate_, i + Code::kTrapCodeOffset)
|
||||
->value();
|
||||
data.landing_offset =
|
||||
protected_instructions
|
||||
->GetValueChecked<Smi>(isolate_, i + Code::kTrapLandingOffset)
|
||||
->value();
|
||||
unpacked.emplace_back(data);
|
||||
}
|
||||
// TODO(eholk): Register the protected instruction information once the
|
||||
// trap handler is in place.
|
||||
}
|
||||
}
|
||||
|
||||
// Set up and link the new instance.
|
||||
//--------------------------------------------------------------------------
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define V8_WASM_OBJECTS_H_
|
||||
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/trap-handler/trap-handler.h"
|
||||
#include "src/wasm/managed.h"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -566,7 +566,7 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
|
||||
CompilationInfo info(debug_name_, this->isolate(), this->zone(),
|
||||
Code::ComputeFlags(Code::WASM_FUNCTION));
|
||||
std::unique_ptr<CompilationJob> job(Pipeline::NewWasmCompilationJob(
|
||||
&info, &jsgraph, desc, &source_position_table_));
|
||||
&info, &jsgraph, desc, &source_position_table_, nullptr));
|
||||
if (job->ExecuteJob() != CompilationJob::SUCCEEDED ||
|
||||
job->FinalizeJob() != CompilationJob::SUCCEEDED)
|
||||
return Handle<Code>::null();
|
||||
|
Loading…
Reference in New Issue
Block a user