Commit 03b543ab authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[runtime] Allocate HandlerTable before Code objects.

This allocates and populates potential exception handler tables before
the underlying {Code} objects is allocated. It essentially makes the
field holding said table immutable after allocation.

R=verwaest@chromium.org
BUG=v8:6792

Change-Id: I52ca374d40e3a72a4de022aca10faead6422db79
Reviewed-on: https://chromium-review.googlesource.com/723299Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48677}
parent f5c6daf1
......@@ -121,12 +121,15 @@ Handle<Code> PlatformCodeStub::GenerateCode() {
Generate(&masm);
}
// Allocate the handler table.
Handle<HandlerTable> table = GenerateHandlerTable();
// Create the code object.
CodeDesc desc;
masm.GetCode(isolate(), &desc);
// Copy the generated code into a heap object.
Handle<Code> new_object = factory->NewCode(
desc, Code::STUB, masm.CodeObject(), NeedsImmovableCode());
desc, Code::STUB, masm.CodeObject(), table, NeedsImmovableCode());
return new_object;
}
......@@ -147,7 +150,6 @@ Handle<Code> CodeStub::GetCode() {
Handle<Code> new_object = GenerateCode();
new_object->set_stub_key(GetKey());
FinishCode(new_object);
RecordCodeGeneration(new_object);
#ifdef ENABLE_DISASSEMBLER
......@@ -222,6 +224,9 @@ void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
}
}
Handle<HandlerTable> PlatformCodeStub::GenerateHandlerTable() {
return HandlerTable::Empty(isolate());
}
static void InitializeDescriptorDispatchedCall(CodeStub* stub,
void** value_out) {
......@@ -459,11 +464,11 @@ TF_STUB(LoadIndexedInterceptorStub, CodeStubAssembler) {
vector);
}
void JSEntryStub::FinishCode(Handle<Code> code) {
Handle<HandlerTable> JSEntryStub::GenerateHandlerTable() {
Handle<FixedArray> handler_table =
code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
isolate()->factory()->NewFixedArray(1, TENURED);
handler_table->set(0, Smi::FromInt(handler_offset_));
code->set_handler_table(*handler_table);
return Handle<HandlerTable>::cast(handler_table);
}
......
......@@ -229,9 +229,6 @@ class CodeStub : public ZoneObject {
// initially generated.
void RecordCodeGeneration(Handle<Code> code);
// Finish the code object after it has been generated.
virtual void FinishCode(Handle<Code> code) { }
// Activate newly generated stub. Is called after
// registering stub in the stub cache.
virtual void Activate(Code* code) { }
......@@ -315,6 +312,9 @@ class PlatformCodeStub : public CodeStub {
// Generates the assembler code for the stub.
virtual void Generate(MacroAssembler* masm) = 0;
// Generates the exception handler table for the stub.
virtual Handle<HandlerTable> GenerateHandlerTable();
DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
};
......@@ -750,7 +750,7 @@ class JSEntryStub : public PlatformCodeStub {
}
private:
void FinishCode(Handle<Code> code) override;
Handle<HandlerTable> GenerateHandlerTable() override;
void PrintName(std::ostream& os) const override { // NOLINT
os << (type() == StackFrame::ENTRY ? "JSEntryStub"
......
......@@ -278,6 +278,18 @@ void CodeGenerator::AssembleCode() {
Handle<Code> CodeGenerator::FinalizeCode() {
if (result_ != kSuccess) return Handle<Code>();
// Allocate exception handler table.
Handle<HandlerTable> table = HandlerTable::Empty(isolate());
if (!handlers_.empty()) {
table = Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())),
TENURED));
for (size_t i = 0; i < handlers_.size(); ++i) {
table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset);
table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos());
}
}
// Allocate and install the code.
CodeDesc desc;
tasm()->GetCode(isolate(), &desc);
......@@ -285,8 +297,8 @@ Handle<Code> CodeGenerator::FinalizeCode() {
unwinding_info_writer_.eh_frame_writer()->GetEhFrame(&desc);
}
Handle<Code> result = isolate()->factory()->NewCode(desc, info()->code_kind(),
Handle<Object>(), false);
Handle<Code> result = isolate()->factory()->NewCode(
desc, info()->code_kind(), Handle<Object>(), table, false);
isolate()->counters()->total_compiled_code_size()->Increment(
result->instruction_size());
result->set_is_turbofanned(true);
......@@ -297,19 +309,6 @@ Handle<Code> CodeGenerator::FinalizeCode() {
isolate(), Handle<AbstractCode>::cast(result));
result->set_source_position_table(*source_positions);
// Emit exception handler table.
if (!handlers_.empty()) {
Handle<HandlerTable> table =
Handle<HandlerTable>::cast(isolate()->factory()->NewFixedArray(
HandlerTable::LengthForReturn(static_cast<int>(handlers_.size())),
TENURED));
for (size_t i = 0; i < handlers_.size(); ++i) {
table->SetReturnOffset(static_cast<int>(i), handlers_[i].pc_offset);
table->SetReturnHandler(static_cast<int>(i), handlers_[i].handler->pos());
}
result->set_handler_table(*table);
}
PopulateDeoptimizationData(result);
return result;
......
......@@ -1784,9 +1784,15 @@ Handle<Code> Factory::NewCodeRaw(int object_size, bool immovable) {
}
Handle<Code> Factory::NewCode(const CodeDesc& desc, Code::Kind kind,
Handle<Object> self_ref, bool immovable) {
Handle<Object> self_ref,
MaybeHandle<HandlerTable> maybe_handler_table,
bool immovable) {
Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED);
Handle<HandlerTable> handler_table =
maybe_handler_table.is_null() ? HandlerTable::Empty(isolate())
: maybe_handler_table.ToHandleChecked();
bool has_unwinding_info = desc.unwinding_info != nullptr;
DCHECK((has_unwinding_info && desc.unwinding_info_size > 0) ||
(!has_unwinding_info && desc.unwinding_info_size == 0));
......@@ -1819,7 +1825,7 @@ Handle<Code> Factory::NewCode(const CodeDesc& desc, Code::Kind kind,
code->set_deoptimization_data(*empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_raw_type_feedback_info(Smi::kZero);
code->set_next_code_link(*undefined_value(), SKIP_WRITE_BARRIER);
code->set_handler_table(*empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_handler_table(*handler_table);
code->set_source_position_table(*empty_byte_array(), SKIP_WRITE_BARRIER);
code->set_constant_pool_offset(desc.instr_size - desc.constant_pool_size);
code->set_builtin_index(-1);
......
......@@ -675,7 +675,10 @@ class V8_EXPORT_PRIVATE Factory final {
// This allows generated code to reference its own Code object
// by containing this handle.
Handle<Code> NewCode(const CodeDesc& desc, Code::Kind kind,
Handle<Object> self_reference, bool immovable = false);
Handle<Object> self_reference,
MaybeHandle<HandlerTable> maybe_handler_table =
MaybeHandle<HandlerTable>(),
bool immovable = false);
// Allocates a new, empty code object for use by builtin deserialization. The
// given {size} argument specifies the size of the entire code object.
......
......@@ -10515,6 +10515,9 @@ int HandlerTable::LookupReturn(int pc_offset) {
return -1;
}
Handle<HandlerTable> HandlerTable::Empty(Isolate* isolate) {
return Handle<HandlerTable>::cast(isolate->factory()->empty_fixed_array());
}
#ifdef DEBUG
bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
......
......@@ -74,6 +74,9 @@ class HandlerTable : public FixedArray {
static int LengthForRange(int entries) { return entries * kRangeEntrySize; }
static int LengthForReturn(int entries) { return entries * kReturnEntrySize; }
// Returns an empty handler table.
static Handle<HandlerTable> Empty(Isolate* isolate);
DECL_CAST(HandlerTable)
#ifdef ENABLE_DISASSEMBLER
......
......@@ -5777,7 +5777,8 @@ Handle<Code> GenerateDummyImmovableCode(Isolate* isolate) {
assm.GetCode(isolate, &desc);
const bool kImmovable = true;
Handle<Code> code =
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>(), kImmovable);
isolate->factory()->NewCode(desc, Code::STUB, Handle<Code>(),
HandlerTable::Empty(isolate), kImmovable);
CHECK(code->IsCode());
return code;
......
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