[nci] Verify native context independent code

After native-context-independent codegen, verify that the resulting
Code object does not embed any nc-dependent objects, and that no code
dependencies have been created.

Bug: v8:8888
Change-Id: I894e74b27e86e7727ff17aa0dbfdd908373a5e55
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2284498
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68757}
This commit is contained in:
Jakob Gruber 2020-07-09 14:05:12 +02:00 committed by Commit Bot
parent f44900d2f1
commit f468e8e75f
6 changed files with 92 additions and 13 deletions

View File

@ -328,6 +328,13 @@ class RelocInfo {
static const int kApplyMask; // Modes affected by apply. Depends on arch.
static constexpr int AllRealModesMask() {
constexpr Mode kFirstUnrealRelocMode =
static_cast<Mode>(RelocInfo::LAST_REAL_RELOC_MODE + 1);
return (ModeMask(kFirstUnrealRelocMode) - 1) &
~(ModeMask(RelocInfo::FIRST_REAL_RELOC_MODE) - 1);
}
static int EmbeddedObjectModeMask() {
return ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT);

View File

@ -513,6 +513,11 @@ MaybeHandle<Code> CodeGenerator::FinalizeCode() {
return MaybeHandle<Code>();
}
// TODO(jgruber,v8:8888): Turn this into a DCHECK once confidence is
// high that the implementation is complete.
CHECK_IMPLIES(info()->native_context_independent(),
code->IsNativeContextIndependent(isolate()));
isolate()->counters()->total_compiled_code_size()->Increment(
code->raw_instruction_size());

View File

@ -505,6 +505,12 @@ bool CompilationDependencies::AreValid() const {
}
bool CompilationDependencies::Commit(Handle<Code> code) {
// Dependencies are context-dependent. In the future it may be possible to
// restore them in the consumer native context, but for now they are
// disabled.
CHECK_IMPLIES(broker_->is_native_context_independent(),
dependencies_.empty());
for (auto dep : dependencies_) {
if (!dep->IsValid()) {
dependencies_.clear();

View File

@ -3760,6 +3760,10 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
start_index = formal_parameter_count;
}
// TODO(jgruber,v8:8888): Attempt to remove this restriction. The reason it
// currently exists is because we cannot create code dependencies in NCI code.
if (broker()->is_native_context_independent()) return NoChange();
// For call/construct with spread, we need to also install a code
// dependency on the array iterator lookup protector cell to ensure
// that no one messed with the %ArrayIteratorPrototype%.next method.

View File

@ -238,15 +238,12 @@ const char* AbstractCode::Kind2String(Kind kind) {
}
bool Code::IsIsolateIndependent(Isolate* isolate) {
constexpr int all_real_modes_mask =
(1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) -
(1 << (RelocInfo::FIRST_REAL_RELOC_MODE - 1)) - 1;
constexpr int mode_mask = all_real_modes_mask &
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
STATIC_ASSERT(mode_mask ==
static constexpr int kModeMask =
RelocInfo::AllRealModesMask() &
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
STATIC_ASSERT(kModeMask ==
(RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
@ -258,8 +255,7 @@ bool Code::IsIsolateIndependent(Isolate* isolate) {
RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL)));
bool is_process_independent = true;
for (RelocIterator it(*this, mode_mask); !it.done(); it.next()) {
for (RelocIterator it(*this, kModeMask); !it.done(); it.next()) {
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS) || \
defined(V8_TARGET_ARCH_S390) || defined(V8_TARGET_ARCH_IA32)
@ -276,10 +272,70 @@ bool Code::IsIsolateIndependent(Isolate* isolate) {
if (Builtins::IsIsolateIndependentBuiltin(target)) continue;
}
#endif
is_process_independent = false;
return false;
}
return is_process_independent;
return true;
}
// Multiple native contexts live on the same heap, and V8 currently
// draws no clear distinction between native-context-dependent and
// independent objects. A good guideline is "objects embedded into
// bytecode are nc-independent", since bytecode is shared between
// native contexts. Among others, this is the case for ScopeInfo,
// SharedFunctionInfo, String, etc.
bool Code::IsNativeContextIndependent(Isolate* isolate) {
static constexpr int kModeMask =
RelocInfo::AllRealModesMask() &
~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
~RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) &
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) &
~RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) &
~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
~RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) &
~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
STATIC_ASSERT(kModeMask ==
(RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::COMPRESSED_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::FULL_EMBEDDED_OBJECT) |
RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL)));
bool is_independent = true;
for (RelocIterator it(*this, kModeMask); !it.done(); it.next()) {
if (RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode())) {
HeapObject o = it.rinfo()->target_object();
// TODO(jgruber,v8:8888): Extend this with further NCI objects,
// and define a more systematic
// IsNativeContextIndependent<T>() predicate.
if (o.IsString()) continue;
if (o.IsScopeInfo()) continue;
if (o.IsHeapNumber()) continue;
if (o.IsBigInt()) continue;
if (o.IsSharedFunctionInfo()) continue;
if (o.IsArrayBoilerplateDescription()) continue;
if (o.IsObjectBoilerplateDescription()) continue;
if (o.IsTemplateObjectDescription()) continue;
if (o.IsFixedArray()) {
// Some uses of FixedArray are valid.
// 1. Passed as arg to %DeclareGlobals, contains only strings
// and SFIs.
// 2. Passed as arg to %DefineClass. No well defined contents.
// .. ?
// TODO(jgruber): Consider assigning dedicated instance
// types instead of assuming fixed arrays are okay.
continue;
}
// Other objects are expected to be context-dependent.
PrintF("Found native-context-dependent object:\n");
o.Print();
o.map().Print();
}
is_independent = false;
}
return is_independent;
}
bool Code::Inlines(SharedFunctionInfo sfi) {

View File

@ -371,6 +371,7 @@ class Code : public HeapObject {
inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction();
bool IsIsolateIndependent(Isolate* isolate);
bool IsNativeContextIndependent(Isolate* isolate);
inline bool CanContainWeakObjects();