}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return target_address();
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return target_address();
os << " (" << Brief(target_object()) << ")";
} else if (rmode_ == EXTERNAL_REFERENCE) {
ExternalReferenceEncoder ref_encoder(isolate);
- os << " (" << ref_encoder.NameOfAddress(target_reference()) << ") ("
- << static_cast<const void*>(target_reference()) << ")";
+ os << " (" << ref_encoder.NameOfAddress(target_external_reference())
+ << ") (" << static_cast<const void*>(target_external_reference())
+ << ")";
} else if (IsCodeTarget(rmode_)) {
Code* code = Code::GetCodeFromTargetAddress(target_address());
os << " (" << Code::Kind2String(code->kind()) << ") ("
// place, ready to be patched with the target.
INLINE(int target_address_size());
+ // Read the reference in the instruction this relocation
+ // applies to; can only be called if rmode_ is EXTERNAL_REFERENCE.
+ INLINE(Address target_external_reference());
+
// Read/modify the reference in the instruction this relocation
- // applies to; can only be called if rmode_ is external_reference
- INLINE(Address target_reference());
+ // applies to; can only be called if rmode_ is INTERNAL_REFERENCE.
+ INLINE(Address target_internal_reference());
+ INLINE(void set_target_internal_reference(Address target));
// Read/modify the address of a call instruction. This is used to relocate
// the break points where straight-line code is patched with a call
}
}
+ // Do not use Crankshaft if the code is intended to be serialized.
+ if (!isolate()->use_crankshaft()) return SetLastStatus(FAILED);
+
if (FLAG_trace_opt) {
OFStream os(stdout);
os << "[compiling method " << Brief(*info()->closure())
PostponeInterruptsScope postpone(isolate);
info.SetOptimizing(BailoutId::None(), handle(function->shared()->code()));
- info.MarkAsContextSpecializing();
if (GetOptimizedCodeNow(&info)) {
DCHECK(function->shared()->is_compiled());
ASSIGN_RETURN_ON_EXCEPTION(isolate, result, GetUnoptimizedCodeCommon(&info),
Code);
- if (FLAG_always_opt && isolate->use_crankshaft()) {
+ if (FLAG_always_opt) {
Handle<Code> opt_code;
if (Compiler::GetOptimizedCode(
function, result,
Isolate* isolate = info->isolate();
DCHECK(AllowCompilation::IsAllowed(isolate));
VMState<COMPILER> state(isolate);
- DCHECK(isolate->use_crankshaft());
DCHECK(!isolate->has_pending_exception());
PostponeInterruptsScope postpone(isolate);
out.AddFormatted(" ;; object: %s", obj_name.get());
} else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
const char* reference_name =
- ref_encoder.NameOfAddress(relocinfo.target_reference());
+ ref_encoder.NameOfAddress(relocinfo.target_external_reference());
out.AddFormatted(" ;; external reference (%s)", reference_name);
} else if (RelocInfo::IsCodeTarget(rmode)) {
out.AddFormatted(" ;; code:");
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
return Memory::Address_at(pc_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_));
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return target_address();
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return target_address();
void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
- Address p = rinfo->target_reference();
+ Address p = rinfo->target_external_reference();
VisitExternalReference(&p);
}
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == EXTERNAL_REFERENCE);
return Assembler::target_address_at(pc_, host_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return target_address();
DCHECK(space_number != CODE_SPACE);
}
#endif
-#if V8_TARGET_ARCH_PPC
- // If we're on a platform that uses function descriptors
- // these jump tables make use of RelocInfo::INTERNAL_REFERENCE.
- // As the V8 serialization code doesn't handle that relocation type
- // we use this to fix up code that has function descriptors.
- if (space_number == CODE_SPACE) {
- Code* code = reinterpret_cast<Code*>(HeapObject::FromAddress(address));
- for (RelocIterator it(code); !it.done(); it.next()) {
- RelocInfo::Mode rmode = it.rinfo()->rmode();
- if (RelocInfo::IsInternalReference(rmode) ||
- RelocInfo::IsInternalReferenceEncoded(rmode)) {
- Assembler::RelocateInternalReference(it.rinfo()->pc(), 0,
- code->instruction_start(), rmode);
- }
+
+ if (obj->IsCode()) {
+ // Turn internal references encoded as offsets back to absolute addresses.
+ Code* code = Code::cast(obj);
+ Address entry = code->entry();
+ int mode_mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE);
+ for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
+ RelocInfo* rinfo = it.rinfo();
+ intptr_t offset =
+ reinterpret_cast<intptr_t>(rinfo->target_internal_reference());
+ DCHECK(0 <= offset && offset <= code->instruction_size());
+ rinfo->set_target_internal_reference(entry + offset);
}
}
-#endif
}
HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef");
sink_->PutInt(skip, "SkipB4ExternalRef");
- Address target = rinfo->target_reference();
+ Address target = rinfo->target_external_reference();
sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id");
bytes_processed_so_far_ += rinfo->target_address_size();
}
Address Serializer::ObjectSerializer::PrepareCode() {
// To make snapshots reproducible, we make a copy of the code object
// and wipe all pointers in the copy, which we then serialize.
- Code* code = serializer_->CopyCode(Code::cast(object_));
+ Code* original = Code::cast(object_);
+ Code* code = serializer_->CopyCode(original);
// Code age headers are not serializable.
code->MakeYoung(serializer_->isolate());
- int mode_mask =
- RelocInfo::kCodeTargetMask |
- RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
- RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
- RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
+ Address entry = original->entry();
+ int mode_mask = RelocInfo::kCodeTargetMask |
+ RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
+ RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
+ RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
+ RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE);
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
- if (!(FLAG_enable_ool_constant_pool && it.rinfo()->IsInConstantPool())) {
- it.rinfo()->WipeOut();
+ RelocInfo* rinfo = it.rinfo();
+ if (RelocInfo::IsInternalReference(rinfo->rmode())) {
+ // Convert internal references to relative offsets.
+ Address target = rinfo->target_internal_reference();
+ intptr_t offset = target - entry;
+ DCHECK(0 <= offset && offset <= original->instruction_size());
+ rinfo->set_target_internal_reference(reinterpret_cast<Address>(offset));
+ } else if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) {
+ rinfo->WipeOut();
}
}
// We need to wipe out the header fields *after* wiping out the
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
return Memory::Address_at(pc_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
void RelocInfo::set_target_object(Object* target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
}
-Address RelocInfo::target_reference() {
+Address RelocInfo::target_external_reference() {
DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
return Memory::Address_at(pc_);
}
+Address RelocInfo::target_internal_reference() {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ return Memory::Address_at(pc_);
+}
+
+
+void RelocInfo::set_target_internal_reference(Address target) {
+ DCHECK(rmode_ == INTERNAL_REFERENCE);
+ Memory::Address_at(pc_) = target;
+}
+
+
Address RelocInfo::target_runtime_entry(Assembler* origin) {
DCHECK(IsRuntimeEntry(rmode_));
return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_));
TEST(PerIsolateSnapshotBlobs) {
+ const char* flag = "--turbo-filter=\"\"";
+ FlagList::SetFlagsFromString(flag, StrLength(flag));
+
const char* source1 = "function f() { return 42; }";
const char* source2 =
"function f() { return g() * 2; }"
}
isolate2->Dispose();
}
+
+
+TEST(SerializeInternalReference) {
+ // Disable experimental natives that are loaded after deserialization.
+ FLAG_turbo_deoptimization = false;
+ FLAG_context_specialization = false;
+ FLAG_always_opt = true;
+ const char* flag = "--turbo-filter=foo";
+ FlagList::SetFlagsFromString(flag, StrLength(flag));
+
+ const char* source =
+ "var foo = (function(stdlib, foreign, heap) {"
+ " function foo(i) {"
+ " i = i|0;"
+ " var j = 0;"
+ " switch (i) {"
+ " case 0:"
+ " case 1: j = 1; break;"
+ " case 2:"
+ " case 3: j = 2; break;"
+ " case 4:"
+ " case 5: j = 3; break;"
+ " default: j = 0; break;"
+ " }"
+ " return j|0;"
+ " }"
+ " return { foo: foo };"
+ "})(this, {}, undefined).foo;"
+ "foo(1);";
+
+ v8::StartupData data = v8::V8::CreateSnapshotDataBlob(source);
+ CHECK(data.data);
+
+ v8::Isolate::CreateParams params;
+ params.snapshot_blob = &data;
+ v8::Isolate* isolate = v8::Isolate::New(params);
+ {
+ v8::Isolate::Scope i_scope(isolate);
+ v8::HandleScope h_scope(isolate);
+ v8::Local<v8::Context> context = v8::Context::New(isolate);
+ delete[] data.data; // We can dispose of the snapshot blob now.
+ v8::Context::Scope c_scope(context);
+ v8::Handle<v8::Function> foo =
+ v8::Handle<v8::Function>::Cast(CompileRun("foo"));
+ CHECK(v8::Utils::OpenHandle(*foo)->code()->is_turbofanned());
+ CHECK_EQ(3, CompileRun("foo(4)")->ToInt32(isolate)->Int32Value());
+ }
+ isolate->Dispose();
+}
'debug-stepin-builtin': [PASS, NO_VARIANTS],
'debug-stepin-constructor': [PASS, NO_VARIANTS],
'debug-stepin-function-call': [PASS, NO_VARIANTS],
+ 'debug-stepin-positions': [PASS, NO_VARIANTS],
+ 'debug-stepin-property-function-call': [PASS, NO_VARIANTS],
'debug-stepnext-do-while': [PASS, NO_VARIANTS],
'debug-stepout-scope-part1': [PASS, NO_VARIANTS],
'debug-stepout-scope-part2': [PASS, NO_VARIANTS],