[heap] Move code mutation scope into {Heap::AllocateCode}.
This makes sure the {CodeSpaceMemoryModificationScope} for the common allocation path is inside the {Heap} component. This will in turn enable finer-grained control of the modification scope in the future. R=hpayer@chromium.org BUG=v8:6792 Change-Id: I6c3bc457bac641e79b2786cf78557b26aa2027e7 Reviewed-on: https://chromium-review.googlesource.com/779399 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Hannes Payer <hpayer@chromium.org> Cr-Commit-Position: refs/heads/master@{#49532}
This commit is contained in:
parent
412f1568f2
commit
ffd36179b9
@ -1746,12 +1746,6 @@ Handle<CodeDataContainer> Factory::NewCodeDataContainer(int flags) {
|
||||
return data_container;
|
||||
}
|
||||
|
||||
Handle<Code> Factory::NewCodeRaw(int object_size, Movability movability) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->AllocateCode(object_size, movability),
|
||||
Code);
|
||||
}
|
||||
|
||||
Handle<Code> Factory::NewCode(
|
||||
const CodeDesc& desc, Code::Kind kind, Handle<Object> self_ref,
|
||||
int32_t builtin_index, MaybeHandle<HandlerTable> maybe_handler_table,
|
||||
@ -1773,78 +1767,18 @@ Handle<Code> Factory::NewCode(
|
||||
maybe_deopt_data.is_null() ? DeoptimizationData::Empty(isolate())
|
||||
: maybe_deopt_data.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));
|
||||
|
||||
// Compute size.
|
||||
int body_size = desc.instr_size;
|
||||
int unwinding_info_size_field_size = kInt64Size;
|
||||
if (has_unwinding_info) {
|
||||
body_size = RoundUp(body_size, kInt64Size) + desc.unwinding_info_size +
|
||||
unwinding_info_size_field_size;
|
||||
}
|
||||
int obj_size = Code::SizeFor(RoundUp(body_size, kObjectAlignment));
|
||||
|
||||
CodeSpaceMemoryModificationScope code_allocation(isolate()->heap());
|
||||
Handle<Code> code = NewCodeRaw(obj_size, movability);
|
||||
DCHECK(!isolate()->heap()->memory_allocator()->code_range()->valid() ||
|
||||
isolate()->heap()->memory_allocator()->code_range()->contains(
|
||||
code->address()) ||
|
||||
obj_size <= isolate()->heap()->code_space()->AreaSize());
|
||||
|
||||
// The code object has not been fully initialized yet. We rely on the
|
||||
// fact that no allocation will happen from this point on.
|
||||
DisallowHeapAllocation no_gc;
|
||||
code->set_instruction_size(desc.instr_size);
|
||||
code->set_relocation_info(*reloc_info);
|
||||
code->initialize_flags(kind, has_unwinding_info, is_turbofanned, stack_slots);
|
||||
code->set_safepoint_table_offset(safepoint_table_offset);
|
||||
code->set_code_data_container(*data_container);
|
||||
code->set_has_tagged_params(true);
|
||||
code->set_deoptimization_data(*deopt_data);
|
||||
code->set_stub_key(stub_key);
|
||||
code->set_handler_table(*handler_table);
|
||||
code->set_source_position_table(*source_position_table);
|
||||
code->set_protected_instructions(*empty_fixed_array(), SKIP_WRITE_BARRIER);
|
||||
code->set_constant_pool_offset(desc.instr_size - desc.constant_pool_size);
|
||||
code->set_builtin_index(builtin_index);
|
||||
code->set_trap_handler_index(Smi::FromInt(-1));
|
||||
|
||||
switch (code->kind()) {
|
||||
case Code::OPTIMIZED_FUNCTION:
|
||||
code->set_marked_for_deoptimization(false);
|
||||
break;
|
||||
case Code::JS_TO_WASM_FUNCTION:
|
||||
case Code::C_WASM_ENTRY:
|
||||
case Code::WASM_FUNCTION:
|
||||
code->set_has_tagged_params(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow self references to created code object by patching the handle to
|
||||
// point to the newly allocated Code object.
|
||||
if (!self_ref.is_null()) *(self_ref.location()) = *code;
|
||||
|
||||
// Migrate generated code.
|
||||
// The generated code can contain Object** values (typically from handles)
|
||||
// that are dereferenced during the copy to point directly to the actual heap
|
||||
// objects. These pointers can include references to the code object itself,
|
||||
// through the self_reference parameter.
|
||||
code->CopyFrom(desc);
|
||||
|
||||
code->clear_padding();
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap) code->ObjectVerify();
|
||||
#endif
|
||||
return code;
|
||||
CALL_HEAP_FUNCTION(
|
||||
isolate(),
|
||||
isolate()->heap()->AllocateCode(
|
||||
desc, kind, self_ref, builtin_index, *reloc_info, *data_container,
|
||||
*handler_table, *source_position_table, *deopt_data, movability,
|
||||
stub_key, is_turbofanned, stack_slots, safepoint_table_offset),
|
||||
Code);
|
||||
}
|
||||
|
||||
Handle<Code> Factory::NewCodeForDeserialization(uint32_t size) {
|
||||
return NewCodeRaw(size, kMovable);
|
||||
CALL_HEAP_FUNCTION(isolate(), isolate()->heap()->AllocateCode(size, kMovable),
|
||||
Code);
|
||||
}
|
||||
|
||||
Handle<Code> Factory::CopyCode(Handle<Code> code) {
|
||||
|
@ -847,9 +847,6 @@ class V8_EXPORT_PRIVATE Factory final {
|
||||
MaybeHandle<String> NewStringFromTwoByte(const uc16* string, int length,
|
||||
PretenureFlag pretenure);
|
||||
|
||||
// Creates a code object that is not yet fully initialized yet.
|
||||
Handle<Code> NewCodeRaw(int object_size, Movability movability);
|
||||
|
||||
// Attempt to find the number in a small cache. If we finds it, return
|
||||
// the string representation of the number. Otherwise return undefined.
|
||||
Handle<Object> GetNumberStringCache(Handle<Object> number);
|
||||
|
@ -3125,6 +3125,85 @@ AllocationResult Heap::AllocateCode(int object_size, Movability movability) {
|
||||
return code;
|
||||
}
|
||||
|
||||
AllocationResult Heap::AllocateCode(
|
||||
const CodeDesc& desc, Code::Kind kind, Handle<Object> self_ref,
|
||||
int32_t builtin_index, ByteArray* reloc_info,
|
||||
CodeDataContainer* data_container, HandlerTable* handler_table,
|
||||
ByteArray* source_position_table, DeoptimizationData* deopt_data,
|
||||
Movability movability, uint32_t stub_key, bool is_turbofanned,
|
||||
int stack_slots, int safepoint_table_offset) {
|
||||
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));
|
||||
|
||||
// Compute size.
|
||||
int body_size = desc.instr_size;
|
||||
int unwinding_info_size_field_size = kInt64Size;
|
||||
if (has_unwinding_info) {
|
||||
body_size = RoundUp(body_size, kInt64Size) + desc.unwinding_info_size +
|
||||
unwinding_info_size_field_size;
|
||||
}
|
||||
int object_size = Code::SizeFor(RoundUp(body_size, kObjectAlignment));
|
||||
|
||||
Code* code = nullptr;
|
||||
CodeSpaceMemoryModificationScope code_allocation(this);
|
||||
AllocationResult allocation = AllocateCode(object_size, movability);
|
||||
if (!allocation.To(&code)) return allocation;
|
||||
|
||||
// The code object has not been fully initialized yet. We rely on the
|
||||
// fact that no allocation will happen from this point on.
|
||||
DisallowHeapAllocation no_gc;
|
||||
code->set_instruction_size(desc.instr_size);
|
||||
code->set_relocation_info(reloc_info);
|
||||
code->initialize_flags(kind, has_unwinding_info, is_turbofanned, stack_slots);
|
||||
code->set_safepoint_table_offset(safepoint_table_offset);
|
||||
code->set_code_data_container(data_container);
|
||||
code->set_has_tagged_params(true);
|
||||
code->set_deoptimization_data(deopt_data);
|
||||
code->set_stub_key(stub_key);
|
||||
code->set_handler_table(handler_table);
|
||||
code->set_source_position_table(source_position_table);
|
||||
code->set_protected_instructions(empty_fixed_array(), SKIP_WRITE_BARRIER);
|
||||
code->set_constant_pool_offset(desc.instr_size - desc.constant_pool_size);
|
||||
code->set_builtin_index(builtin_index);
|
||||
code->set_trap_handler_index(Smi::FromInt(-1));
|
||||
|
||||
switch (code->kind()) {
|
||||
case Code::OPTIMIZED_FUNCTION:
|
||||
code->set_marked_for_deoptimization(false);
|
||||
break;
|
||||
case Code::JS_TO_WASM_FUNCTION:
|
||||
case Code::C_WASM_ENTRY:
|
||||
case Code::WASM_FUNCTION:
|
||||
code->set_has_tagged_params(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Allow self references to created code object by patching the handle to
|
||||
// point to the newly allocated Code object.
|
||||
if (!self_ref.is_null()) *(self_ref.location()) = code;
|
||||
|
||||
// Migrate generated code.
|
||||
// The generated code can contain Object** values (typically from handles)
|
||||
// that are dereferenced during the copy to point directly to the actual heap
|
||||
// objects. These pointers can include references to the code object itself,
|
||||
// through the self_reference parameter.
|
||||
code->CopyFrom(desc);
|
||||
|
||||
code->clear_padding();
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap) code->ObjectVerify();
|
||||
#endif
|
||||
DCHECK(IsAligned(bit_cast<intptr_t>(code->address()), kCodeAlignment));
|
||||
DCHECK(!memory_allocator()->code_range()->valid() ||
|
||||
memory_allocator()->code_range()->contains(code->address()) ||
|
||||
object_size <= code_space()->AreaSize());
|
||||
return code;
|
||||
}
|
||||
|
||||
AllocationResult Heap::CopyCode(Code* code, CodeDataContainer* data_container) {
|
||||
CodeSpaceMemoryModificationScope code_modification(this);
|
||||
AllocationResult allocation;
|
||||
@ -3150,16 +3229,20 @@ AllocationResult Heap::CopyCode(Code* code, CodeDataContainer* data_container) {
|
||||
new_code->set_trap_handler_index(Smi::FromInt(trap_handler::kInvalidIndex));
|
||||
|
||||
// Relocate the copy.
|
||||
DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment));
|
||||
DCHECK(!memory_allocator()->code_range()->valid() ||
|
||||
memory_allocator()->code_range()->contains(code->address()) ||
|
||||
obj_size <= code_space()->AreaSize());
|
||||
new_code->Relocate(new_addr - old_addr);
|
||||
// We have to iterate over the object and process its pointers when black
|
||||
// allocation is on.
|
||||
incremental_marking()->ProcessBlackAllocatedObject(new_code);
|
||||
// Record all references to embedded objects in the new code object.
|
||||
RecordWritesIntoCode(new_code);
|
||||
|
||||
#ifdef VERIFY_HEAP
|
||||
if (FLAG_verify_heap) new_code->ObjectVerify();
|
||||
#endif
|
||||
DCHECK(IsAligned(bit_cast<intptr_t>(new_code->address()), kCodeAlignment));
|
||||
DCHECK(!memory_allocator()->code_range()->valid() ||
|
||||
memory_allocator()->code_range()->contains(new_code->address()) ||
|
||||
obj_size <= code_space()->AreaSize());
|
||||
return new_code;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "src/globals.h"
|
||||
#include "src/heap-symbols.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/objects/code.h"
|
||||
#include "src/objects/hash-table.h"
|
||||
#include "src/objects/string-table.h"
|
||||
#include "src/visitors.h"
|
||||
@ -39,6 +40,8 @@ class TestMemoryAllocatorScope;
|
||||
|
||||
class BytecodeArray;
|
||||
class CodeDataContainer;
|
||||
class DeoptimizationData;
|
||||
class HandlerTable;
|
||||
class JSArrayBuffer;
|
||||
|
||||
using v8::MemoryPressureLevel;
|
||||
@ -2251,9 +2254,21 @@ class Heap {
|
||||
MUST_USE_RESULT AllocationResult
|
||||
AllocateForeign(Address address, PretenureFlag pretenure = NOT_TENURED);
|
||||
|
||||
// Allocates a new code object (mostly uninitialized). Can only be used when
|
||||
// code space is unprotected and requires manual initialization by the caller.
|
||||
MUST_USE_RESULT AllocationResult AllocateCode(int object_size,
|
||||
Movability movability);
|
||||
|
||||
// Allocates a new code object (fully initialized). All header fields of the
|
||||
// returned object are immutable and the code object is write protected.
|
||||
MUST_USE_RESULT AllocationResult
|
||||
AllocateCode(const CodeDesc& desc, Code::Kind kind, Handle<Object> self_ref,
|
||||
int32_t builtin_index, ByteArray* reloc_info,
|
||||
CodeDataContainer* data_container, HandlerTable* handler_table,
|
||||
ByteArray* source_position_table, DeoptimizationData* deopt_data,
|
||||
Movability movability, uint32_t stub_key, bool is_turbofanned,
|
||||
int stack_slots, int safepoint_table_offset);
|
||||
|
||||
void set_force_oom(bool value) { force_oom_ = value; }
|
||||
|
||||
// ===========================================================================
|
||||
|
Loading…
Reference in New Issue
Block a user