Commit 07db5a65 authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

Reland "[TurboFan] Move FunctionTemplateInfo to never serialized"

This reverts commit c85b7a44.

This reland fixes missing serialization of objects stored in
CallHandlerInfo::data by adding necessary handling of these objects
in FunctionTemplateInfoRef::SerializeCallCode when running with
direct heap access.

Drive-by: Remove declaration of CallHandlerInfoRef::Serialize, which
did not have a definition.

Original change's description:
> [TurboFan] Move FunctionTemplateInfo to never serialized
>
> This CL moves FunctionTemplateInfo to the list of never serialized
> objects, allowing direct heap reads. To make this threadsafe, the CL:
> - adds necessary atomic (relaxed/acquire-release) operations to the
>   accessors of FunctionTemplateInfo.
> - changes FunctionTemplateInfoRef::LookupHolderOfExpectedType to be
>   usable from the background thread (e.g. no handle construction) with
>   the caveat of skipping optimization in some cases where necessary
>   JSObjects are not serialized.
>
> Drive-by: Add missing serialization of objects possibly reachable
> through CallHandlerInfo::data.
>
> Bug: v8:7790
> Change-Id: I49cf4f328ecfab368dff9076fde8f5783ead3246
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2679687
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Georg Neis <neis@chromium.org>
> Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#73364}

Bug: v8:7790, chromium:1188563
Change-Id: Ib43f1eaf0592d2565292e86dea5acfc41a58f637
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2773807Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73599}
parent e7355231
...@@ -58,12 +58,13 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask { ...@@ -58,12 +58,13 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
private: private:
// v8::Task overrides. // v8::Task overrides.
void RunInternal() override { void RunInternal() override {
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground); WorkerThreadRuntimeCallStatsScope runtime_call_stats_scope(
worker_thread_runtime_call_stats_);
LocalIsolate local_isolate(isolate_, ThreadKind::kBackground,
runtime_call_stats_scope.Get());
DCHECK(local_isolate.heap()->IsParked()); DCHECK(local_isolate.heap()->IsParked());
{ {
WorkerThreadRuntimeCallStatsScope runtime_call_stats_scope(
worker_thread_runtime_call_stats_);
RuntimeCallTimerScope runtimeTimer( RuntimeCallTimerScope runtimeTimer(
runtime_call_stats_scope.Get(), runtime_call_stats_scope.Get(),
RuntimeCallCounterId::kOptimizeBackgroundDispatcherJob); RuntimeCallCounterId::kOptimizeBackgroundDispatcherJob);
......
...@@ -87,6 +87,7 @@ enum class OddballType : uint8_t { ...@@ -87,6 +87,7 @@ enum class OddballType : uint8_t {
V(DescriptorArray) \ V(DescriptorArray) \
V(FeedbackCell) \ V(FeedbackCell) \
V(FeedbackVector) \ V(FeedbackVector) \
V(FunctionTemplateInfo) \
V(Name) \ V(Name) \
V(RegExpBoilerplateDescription) \ V(RegExpBoilerplateDescription) \
V(SharedFunctionInfo) \ V(SharedFunctionInfo) \
...@@ -136,7 +137,6 @@ enum class OddballType : uint8_t { ...@@ -136,7 +137,6 @@ enum class OddballType : uint8_t {
/* Subtypes of HeapObject */ \ /* Subtypes of HeapObject */ \
V(AllocationSite) \ V(AllocationSite) \
V(FixedArrayBase) \ V(FixedArrayBase) \
V(FunctionTemplateInfo) \
V(JSReceiver) \ V(JSReceiver) \
V(SourceTextModule) \ V(SourceTextModule) \
/* Subtypes of Object */ \ /* Subtypes of Object */ \
...@@ -192,6 +192,7 @@ class V8_EXPORT_PRIVATE ObjectRef { ...@@ -192,6 +192,7 @@ class V8_EXPORT_PRIVATE ObjectRef {
HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(HEAP_AS_METHOD_DECL) HEAP_BROKER_NEVER_SERIALIZED_OBJECT_LIST(HEAP_AS_METHOD_DECL)
#undef HEAP_AS_METHOD_DECL #undef HEAP_AS_METHOD_DECL
bool IsNull() const;
bool IsNullOrUndefined() const; bool IsNullOrUndefined() const;
bool IsTheHole() const; bool IsTheHole() const;
...@@ -603,8 +604,6 @@ class CallHandlerInfoRef : public HeapObjectRef { ...@@ -603,8 +604,6 @@ class CallHandlerInfoRef : public HeapObjectRef {
Handle<CallHandlerInfo> object() const; Handle<CallHandlerInfo> object() const;
Address callback() const; Address callback() const;
void Serialize();
ObjectRef data() const; ObjectRef data() const;
}; };
......
...@@ -164,6 +164,7 @@ class ObjectData : public ZoneObject { ...@@ -164,6 +164,7 @@ class ObjectData : public ZoneObject {
kind_ == kNeverSerializedHeapObject || kind_ == kNeverSerializedHeapObject ||
kind_ == kUnserializedReadOnlyHeapObject; kind_ == kUnserializedReadOnlyHeapObject;
} }
bool IsNull() const { return object_->IsNull(); }
#ifdef DEBUG #ifdef DEBUG
enum class Usage{kUnused, kOnlyIdentityUsed, kDataUsed}; enum class Usage{kUnused, kOnlyIdentityUsed, kDataUsed};
...@@ -271,6 +272,7 @@ FunctionTemplateInfoData::FunctionTemplateInfoData( ...@@ -271,6 +272,7 @@ FunctionTemplateInfoData::FunctionTemplateInfoData(
c_function_(v8::ToCData<Address>(object->GetCFunction())), c_function_(v8::ToCData<Address>(object->GetCFunction())),
c_signature_(v8::ToCData<CFunctionInfo*>(object->GetCSignature())), c_signature_(v8::ToCData<CFunctionInfo*>(object->GetCSignature())),
known_receivers_(broker->zone()) { known_receivers_(broker->zone()) {
DCHECK(!FLAG_turbo_direct_heap_access);
auto function_template_info = Handle<FunctionTemplateInfo>::cast(object); auto function_template_info = Handle<FunctionTemplateInfo>::cast(object);
is_signature_undefined_ = is_signature_undefined_ =
function_template_info->signature().IsUndefined(broker->isolate()); function_template_info->signature().IsUndefined(broker->isolate());
...@@ -3507,8 +3509,10 @@ BIMODAL_ACCESSOR_C(RegExpBoilerplateDescription, int, flags) ...@@ -3507,8 +3509,10 @@ BIMODAL_ACCESSOR_C(RegExpBoilerplateDescription, int, flags)
base::Optional<CallHandlerInfoRef> FunctionTemplateInfoRef::call_code() const { base::Optional<CallHandlerInfoRef> FunctionTemplateInfoRef::call_code() const {
if (data_->should_access_heap()) { if (data_->should_access_heap()) {
return CallHandlerInfoRef(broker(), broker()->CanonicalPersistentHandle( HeapObject call_code = object()->call_code(kAcquireLoad);
object()->call_code(kAcquireLoad))); if (call_code.IsUndefined()) return base::nullopt;
return CallHandlerInfoRef(broker(),
broker()->CanonicalPersistentHandle(call_code));
} }
ObjectData* call_code = data()->AsFunctionTemplateInfo()->call_code(); ObjectData* call_code = data()->AsFunctionTemplateInfo()->call_code();
if (!call_code) return base::nullopt; if (!call_code) return base::nullopt;
...@@ -3524,40 +3528,72 @@ bool FunctionTemplateInfoRef::is_signature_undefined() const { ...@@ -3524,40 +3528,72 @@ bool FunctionTemplateInfoRef::is_signature_undefined() const {
bool FunctionTemplateInfoRef::has_call_code() const { bool FunctionTemplateInfoRef::has_call_code() const {
if (data_->should_access_heap()) { if (data_->should_access_heap()) {
CallOptimization call_optimization(broker()->isolate(), object()); HeapObject call_code = object()->call_code(kAcquireLoad);
return call_optimization.is_simple_api_call(); return !call_code.IsUndefined();
} }
return data()->AsFunctionTemplateInfo()->has_call_code(); return data()->AsFunctionTemplateInfo()->has_call_code();
} }
BIMODAL_ACCESSOR_C(FunctionTemplateInfo, bool, accept_any_receiver) bool FunctionTemplateInfoRef ::accept_any_receiver() const {
if (data_->should_access_heap()) {
return object()->accept_any_receiver();
}
return ObjectRef ::data()->AsFunctionTemplateInfo()->accept_any_receiver();
}
HolderLookupResult FunctionTemplateInfoRef::LookupHolderOfExpectedType( HolderLookupResult FunctionTemplateInfoRef::LookupHolderOfExpectedType(
MapRef receiver_map, SerializationPolicy policy) { MapRef receiver_map, SerializationPolicy policy) {
const HolderLookupResult not_found; const HolderLookupResult not_found;
if (data_->should_access_heap()) { if (data_->should_access_heap()) {
CallOptimization call_optimization(broker()->isolate(), object()); // There are currently two ways we can see a FunctionTemplateInfo on the
Handle<Map> receiver_map_ref(receiver_map.object()); // background thread: 1.) As part of a SharedFunctionInfo and 2.) in an
if (!receiver_map_ref->IsJSReceiverMap() || // AccessorPair. In both cases, the FTI is fully constructed on the main
(receiver_map_ref->is_access_check_needed() && // thread before.
// TODO(nicohartmann@, v8:7790): Once the above no longer holds, we might
// have to use the GC predicate to check whether objects are fully
// initialized and safe to read.
if (!receiver_map.IsJSReceiverMap() ||
(receiver_map.is_access_check_needed() &&
!object()->accept_any_receiver())) { !object()->accept_any_receiver())) {
return not_found; return not_found;
} }
HolderLookupResult result; if (!receiver_map.IsJSObjectMap()) return not_found;
Handle<JSObject> holder = call_optimization.LookupHolderOfExpectedType(
receiver_map_ref, &result.lookup);
switch (result.lookup) { DCHECK(has_call_code());
case CallOptimization::kHolderFound:
result.holder = JSObjectRef(broker(), holder); DisallowGarbageCollection no_gc;
break; HeapObject signature = object()->signature();
default: if (signature.IsUndefined()) {
DCHECK_EQ(result.holder, base::nullopt); return HolderLookupResult(CallOptimization::kHolderIsReceiver);
break;
} }
return result; auto expected_receiver_type = FunctionTemplateInfo::cast(signature);
if (expected_receiver_type.IsTemplateFor(*receiver_map.object())) {
return HolderLookupResult(CallOptimization::kHolderIsReceiver);
}
if (!receiver_map.IsJSGlobalProxyMap()) return not_found;
if (policy == SerializationPolicy::kSerializeIfNeeded) {
receiver_map.SerializePrototype();
}
if (!receiver_map.serialized_prototype()) return not_found;
if (receiver_map.prototype().IsNull()) return not_found;
JSObject raw_prototype = JSObject::cast(*receiver_map.prototype().object());
if (!expected_receiver_type.IsTemplateFor(raw_prototype.map())) {
return not_found;
}
Handle<JSObject> prototype =
broker()->CanonicalPersistentHandle(raw_prototype);
if (ObjectData* data = broker()->TryGetOrCreateData(prototype)) {
return HolderLookupResult(CallOptimization::kHolderFound,
JSObjectRef(broker(), data));
}
TRACE_BROKER_MISSING(broker(),
"holder for receiver with map " << receiver_map);
return not_found;
} }
FunctionTemplateInfoData* fti_data = data()->AsFunctionTemplateInfo(); FunctionTemplateInfoData* fti_data = data()->AsFunctionTemplateInfo();
...@@ -3894,6 +3930,8 @@ base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction( ...@@ -3894,6 +3930,8 @@ base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
} }
} }
bool ObjectRef::IsNull() const { return object()->IsNull(); }
bool ObjectRef::IsNullOrUndefined() const { bool ObjectRef::IsNullOrUndefined() const {
if (IsSmi()) return false; if (IsSmi()) return false;
OddballType type = AsHeapObject().map().oddball_type(); OddballType type = AsHeapObject().map().oddball_type();
...@@ -4548,8 +4586,8 @@ void MapRef::SerializePrototype() { ...@@ -4548,8 +4586,8 @@ void MapRef::SerializePrototype() {
} }
bool MapRef::serialized_prototype() const { bool MapRef::serialized_prototype() const {
CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
if (data_->should_access_heap()) return true; if (data_->should_access_heap()) return true;
CHECK_NE(broker()->mode(), JSHeapBroker::kDisabled);
return data()->AsMap()->serialized_prototype(); return data()->AsMap()->serialized_prototype();
} }
...@@ -4613,7 +4651,19 @@ bool PropertyCellRef::Serialize() const { ...@@ -4613,7 +4651,19 @@ bool PropertyCellRef::Serialize() const {
} }
void FunctionTemplateInfoRef::SerializeCallCode() { void FunctionTemplateInfoRef::SerializeCallCode() {
if (data_->should_access_heap()) return; if (data_->should_access_heap()) {
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
// CallHandlerInfo::data may still hold a serialized heap object, so we
// have to make the broker aware of it.
// TODO(v8:7790): Remove this case once ObjectRef is never serialized.
Handle<HeapObject> call_code(object()->call_code(kAcquireLoad),
broker()->isolate());
if (call_code->IsCallHandlerInfo()) {
broker()->GetOrCreateData(
Handle<CallHandlerInfo>::cast(call_code)->data());
}
return;
}
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing); CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsFunctionTemplateInfo()->SerializeCallCode(broker()); data()->AsFunctionTemplateInfo()->SerializeCallCode(broker());
} }
......
...@@ -2260,16 +2260,12 @@ void SerializerForBackgroundCompilation::ProcessCallVarArgs( ...@@ -2260,16 +2260,12 @@ void SerializerForBackgroundCompilation::ProcessCallVarArgs(
void SerializerForBackgroundCompilation::ProcessApiCall( void SerializerForBackgroundCompilation::ProcessApiCall(
Handle<SharedFunctionInfo> target, const HintsVector& arguments) { Handle<SharedFunctionInfo> target, const HintsVector& arguments) {
ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle( for (const auto b :
Builtins::kCallFunctionTemplate_CheckAccess)); {Builtins::kCallFunctionTemplate_CheckAccess,
ObjectRef(broker(), Builtins::kCallFunctionTemplate_CheckCompatibleReceiver,
broker()->isolate()->builtins()->builtin_handle( Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver}) {
Builtins::kCallFunctionTemplate_CheckCompatibleReceiver)); ObjectRef(broker(), broker()->isolate()->builtins()->builtin_handle(b));
ObjectRef( }
broker(),
broker()->isolate()->builtins()->builtin_handle(
Builtins::kCallFunctionTemplate_CheckAccessAndCompatibleReceiver));
FunctionTemplateInfoRef target_template_info( FunctionTemplateInfoRef target_template_info(
broker(), broker(),
broker()->CanonicalPersistentHandle(target->function_data(kAcquireLoad))); broker()->CanonicalPersistentHandle(target->function_data(kAcquireLoad)));
......
...@@ -2098,7 +2098,7 @@ void FunctionTemplateInfo::FunctionTemplateInfoPrint( ...@@ -2098,7 +2098,7 @@ void FunctionTemplateInfo::FunctionTemplateInfoPrint(
os << "\n - undetectable: " << (undetectable() ? "true" : "false"); os << "\n - undetectable: " << (undetectable() ? "true" : "false");
os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false"); os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
os << "\n - instantiated: " << (instantiated() ? "true" : "false"); os << "\n - instantiated: " << (instantiated() ? "true" : "false");
os << "\n - rare_data: " << Brief(rare_data()); os << "\n - rare_data: " << Brief(rare_data(kAcquireLoad));
os << "\n"; os << "\n";
} }
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind) LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind,
RuntimeCallStats* runtime_call_stats)
: HiddenLocalFactory(isolate), : HiddenLocalFactory(isolate),
heap_(isolate->heap(), kind), heap_(isolate->heap(), kind),
isolate_(isolate), isolate_(isolate),
...@@ -20,7 +21,8 @@ LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind) ...@@ -20,7 +21,8 @@ LocalIsolate::LocalIsolate(Isolate* isolate, ThreadKind kind)
thread_id_(ThreadId::Current()), thread_id_(ThreadId::Current()),
stack_limit_(kind == ThreadKind::kMain stack_limit_(kind == ThreadKind::kMain
? isolate->stack_guard()->real_climit() ? isolate->stack_guard()->real_climit()
: GetCurrentStackPosition() - FLAG_stack_size * KB) {} : GetCurrentStackPosition() - FLAG_stack_size * KB),
runtime_call_stats_(runtime_call_stats) {}
LocalIsolate::~LocalIsolate() = default; LocalIsolate::~LocalIsolate() = default;
......
...@@ -19,6 +19,7 @@ namespace internal { ...@@ -19,6 +19,7 @@ namespace internal {
class Isolate; class Isolate;
class LocalLogger; class LocalLogger;
class RuntimeCallStats;
// HiddenLocalFactory parallels Isolate's HiddenFactory // HiddenLocalFactory parallels Isolate's HiddenFactory
class V8_EXPORT_PRIVATE HiddenLocalFactory : private LocalFactory { class V8_EXPORT_PRIVATE HiddenLocalFactory : private LocalFactory {
...@@ -37,7 +38,8 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { ...@@ -37,7 +38,8 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
public: public:
using HandleScopeType = LocalHandleScope; using HandleScopeType = LocalHandleScope;
explicit LocalIsolate(Isolate* isolate, ThreadKind kind); explicit LocalIsolate(Isolate* isolate, ThreadKind kind,
RuntimeCallStats* runtime_call_stats = nullptr);
~LocalIsolate(); ~LocalIsolate();
// Kinda sketchy. // Kinda sketchy.
...@@ -84,6 +86,7 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { ...@@ -84,6 +86,7 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
LocalLogger* logger() const { return logger_.get(); } LocalLogger* logger() const { return logger_.get(); }
ThreadId thread_id() const { return thread_id_; } ThreadId thread_id() const { return thread_id_; }
Address stack_limit() const { return stack_limit_; } Address stack_limit() const { return stack_limit_; }
RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; }
bool is_main_thread() const { return heap_.is_main_thread(); } bool is_main_thread() const { return heap_.is_main_thread(); }
...@@ -101,6 +104,8 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory { ...@@ -101,6 +104,8 @@ class V8_EXPORT_PRIVATE LocalIsolate final : private HiddenLocalFactory {
std::unique_ptr<LocalLogger> logger_; std::unique_ptr<LocalLogger> logger_;
ThreadId const thread_id_; ThreadId const thread_id_;
Address const stack_limit_; Address const stack_limit_;
RuntimeCallStats* runtime_call_stats_;
}; };
template <base::MutexSharedType kIsShared> template <base::MutexSharedType kIsShared>
......
...@@ -88,16 +88,14 @@ bool CallOptimization::IsCompatibleReceiverMap( ...@@ -88,16 +88,14 @@ bool CallOptimization::IsCompatibleReceiverMap(
void CallOptimization::Initialize( void CallOptimization::Initialize(
Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) { Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
if (function_template_info->call_code(kAcquireLoad).IsUndefined(isolate)) HeapObject call_code = function_template_info->call_code(kAcquireLoad);
return; if (call_code.IsUndefined(isolate)) return;
api_call_info_ = handle( api_call_info_ = handle(CallHandlerInfo::cast(call_code), isolate);
CallHandlerInfo::cast(function_template_info->call_code(kAcquireLoad)),
isolate);
if (!function_template_info->signature().IsUndefined(isolate)) { HeapObject signature = function_template_info->signature();
if (!signature.IsUndefined(isolate)) {
expected_receiver_type_ = expected_receiver_type_ =
handle(FunctionTemplateInfo::cast(function_template_info->signature()), handle(FunctionTemplateInfo::cast(signature), isolate);
isolate);
} }
is_simple_api_call_ = true; is_simple_api_call_ = true;
} }
......
...@@ -351,6 +351,19 @@ ...@@ -351,6 +351,19 @@
set_##field(BooleanBit::set(field(), offset, value)); \ set_##field(BooleanBit::set(field(), offset, value)); \
} }
#define DECL_RELAXED_BOOL_ACCESSORS(name) \
inline bool name(RelaxedLoadTag) const; \
inline void set_##name(bool value, RelaxedStoreTag);
#define RELAXED_BOOL_ACCESSORS(holder, field, name, offset) \
bool holder::name(RelaxedLoadTag) const { \
return BooleanBit::get(field(kRelaxedLoad), offset); \
} \
void holder::set_##name(bool value, RelaxedStoreTag) { \
set_##field(BooleanBit::set(field(kRelaxedLoad), offset, value), \
kRelaxedStore); \
}
#define BIT_FIELD_ACCESSORS2(holder, get_field, set_field, name, BitField) \ #define BIT_FIELD_ACCESSORS2(holder, get_field, set_field, name, BitField) \
typename BitField::FieldType holder::name() const { \ typename BitField::FieldType holder::name() const { \
return BitField::decode(get_field()); \ return BitField::decode(get_field()); \
......
...@@ -1314,8 +1314,12 @@ Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo( ...@@ -1314,8 +1314,12 @@ Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
} }
bool FunctionTemplateInfo::IsTemplateFor(Map map) { bool FunctionTemplateInfo::IsTemplateFor(Map map) {
RuntimeCallTimerScope timer(GetIsolate(), RuntimeCallTimerScope timer(
RuntimeCallCounterId::kIsTemplateFor); LocalHeap::Current() == nullptr
? GetIsolate()->counters()->runtime_call_stats()
: LocalIsolate::FromHeap(LocalHeap::Current())->runtime_call_stats(),
RuntimeCallCounterId::kIsTemplateFor);
// There is a constraint on the object; check. // There is a constraint on the object; check.
if (!map.IsJSObjectMap()) return false; if (!map.IsJSObjectMap()) return false;
// Fetch the constructor function of the object. // Fetch the constructor function of the object.
...@@ -1342,14 +1346,14 @@ bool FunctionTemplateInfo::IsTemplateFor(Map map) { ...@@ -1342,14 +1346,14 @@ bool FunctionTemplateInfo::IsTemplateFor(Map map) {
// static // static
FunctionTemplateRareData FunctionTemplateInfo::AllocateFunctionTemplateRareData( FunctionTemplateRareData FunctionTemplateInfo::AllocateFunctionTemplateRareData(
Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) { Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
DCHECK(function_template_info->rare_data().IsUndefined(isolate)); DCHECK(function_template_info->rare_data(kAcquireLoad).IsUndefined(isolate));
Handle<Struct> struct_obj = isolate->factory()->NewStruct( Handle<Struct> struct_obj = isolate->factory()->NewStruct(
FUNCTION_TEMPLATE_RARE_DATA_TYPE, AllocationType::kOld); FUNCTION_TEMPLATE_RARE_DATA_TYPE, AllocationType::kOld);
Handle<FunctionTemplateRareData> rare_data = Handle<FunctionTemplateRareData> rare_data =
i::Handle<FunctionTemplateRareData>::cast(struct_obj); i::Handle<FunctionTemplateRareData>::cast(struct_obj);
rare_data->set_c_function(Smi(0)); rare_data->set_c_function(Smi(0));
rare_data->set_c_signature(Smi(0)); rare_data->set_c_signature(Smi(0));
function_template_info->set_rare_data(*rare_data); function_template_info->set_rare_data(*rare_data, kReleaseStore);
return *rare_data; return *rare_data;
} }
......
...@@ -39,13 +39,33 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, ...@@ -39,13 +39,33 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver,
AcceptAnyReceiverBit::kShift) AcceptAnyReceiverBit::kShift)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, published, PublishedBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, published, PublishedBit::kShift)
// TODO(nicohartmann@, v8:11122): Let Torque generate this accessor.
RELEASE_ACQUIRE_ACCESSORS(FunctionTemplateInfo, call_code, HeapObject, RELEASE_ACQUIRE_ACCESSORS(FunctionTemplateInfo, call_code, HeapObject,
kCallCodeOffset) kCallCodeOffset)
// TODO(nicohartmann@, v8:11122): Let Torque generate this accessor.
HeapObject FunctionTemplateInfo::rare_data(AcquireLoadTag) const {
IsolateRoot isolate = GetIsolateForPtrCompr(*this);
return rare_data(isolate, kAcquireLoad);
}
HeapObject FunctionTemplateInfo::rare_data(IsolateRoot isolate,
AcquireLoadTag) const {
HeapObject value =
TaggedField<HeapObject>::Acquire_Load(isolate, *this, kRareDataOffset);
DCHECK(value.IsUndefined() || value.IsFunctionTemplateRareData());
return value;
}
void FunctionTemplateInfo::set_rare_data(HeapObject value, ReleaseStoreTag,
WriteBarrierMode mode) {
DCHECK(value.IsUndefined() || value.IsFunctionTemplateRareData());
RELEASE_WRITE_FIELD(*this, kRareDataOffset, value);
CONDITIONAL_WRITE_BARRIER(*this, kRareDataOffset, value, mode);
}
// static // static
FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData( FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData(
Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) { Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
HeapObject extra = function_template_info->rare_data(isolate); HeapObject extra = function_template_info->rare_data(isolate, kAcquireLoad);
if (extra.IsUndefined(isolate)) { if (extra.IsUndefined(isolate)) {
return AllocateFunctionTemplateRareData(isolate, function_template_info); return AllocateFunctionTemplateRareData(isolate, function_template_info);
} else { } else {
...@@ -55,7 +75,7 @@ FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData( ...@@ -55,7 +75,7 @@ FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData(
#define RARE_ACCESSORS(Name, CamelName, Type, Default) \ #define RARE_ACCESSORS(Name, CamelName, Type, Default) \
DEF_GETTER(FunctionTemplateInfo, Get##CamelName, Type) { \ DEF_GETTER(FunctionTemplateInfo, Get##CamelName, Type) { \
HeapObject extra = rare_data(isolate); \ HeapObject extra = rare_data(isolate, kAcquireLoad); \
HeapObject undefined = GetReadOnlyRoots(isolate).undefined_value(); \ HeapObject undefined = GetReadOnlyRoots(isolate).undefined_value(); \
return extra == undefined ? Default \ return extra == undefined ? Default \
: FunctionTemplateRareData::cast(extra).Name(); \ : FunctionTemplateRareData::cast(extra).Name(); \
......
...@@ -87,8 +87,16 @@ class FunctionTemplateInfo ...@@ -87,8 +87,16 @@ class FunctionTemplateInfo
DECL_RARE_ACCESSORS(c_signature, CSignature, Object) DECL_RARE_ACCESSORS(c_signature, CSignature, Object)
#undef DECL_RARE_ACCESSORS #undef DECL_RARE_ACCESSORS
// TODO(nicohartmann@, v8:11122): Let Torque generate the following accessor.
DECL_RELEASE_ACQUIRE_ACCESSORS(call_code, HeapObject) DECL_RELEASE_ACQUIRE_ACCESSORS(call_code, HeapObject)
// TODO(nicohartmann@, v8:11122): Let Torque generate the following accessor.
inline HeapObject rare_data(AcquireLoadTag) const;
inline HeapObject rare_data(IsolateRoot isolate, AcquireLoadTag) const;
inline void set_rare_data(
HeapObject value, ReleaseStoreTag,
WriteBarrierMode mode = WriteBarrierMode::UPDATE_WRITE_BARRIER);
// Begin flag bits --------------------- // Begin flag bits ---------------------
DECL_BOOLEAN_ACCESSORS(undetectable) DECL_BOOLEAN_ACCESSORS(undetectable)
......
...@@ -52,7 +52,7 @@ extern class FunctionTemplateInfo extends TemplateInfo { ...@@ -52,7 +52,7 @@ extern class FunctionTemplateInfo extends TemplateInfo {
// If any of the setters declared by DECL_RARE_ACCESSORS are used then a // If any of the setters declared by DECL_RARE_ACCESSORS are used then a
// FunctionTemplateRareData will be stored here. Until then this contains // FunctionTemplateRareData will be stored here. Until then this contains
// undefined. // undefined.
@acquireRead @releaseWrite rare_data: FunctionTemplateRareData|Undefined; rare_data: FunctionTemplateRareData|Undefined;
shared_function_info: SharedFunctionInfo|Undefined; shared_function_info: SharedFunctionInfo|Undefined;
// Internal field to store a flag bitfield. // Internal field to store a flag bitfield.
flag: SmiTagged<FunctionTemplateInfoFlags>; flag: SmiTagged<FunctionTemplateInfoFlags>;
......
...@@ -381,6 +381,45 @@ THREADED_TEST(ReceiverSignature) { ...@@ -381,6 +381,45 @@ THREADED_TEST(ReceiverSignature) {
} }
} }
static void DoNothingCallback(const v8::FunctionCallbackInfo<v8::Value>&) {}
// Regression test for issue chromium:1188563.
THREADED_TEST(Regress1188563) {
i::FLAG_allow_natives_syntax = true;
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
// Set up some data for CallHandlerInfo.
v8::Local<v8::FunctionTemplate> data_constructor_templ =
v8::FunctionTemplate::New(isolate);
v8::Local<Function> data_constructor =
data_constructor_templ->GetFunction(env.local()).ToLocalChecked();
v8::Local<v8::Object> data =
data_constructor->NewInstance(env.local()).ToLocalChecked();
// Setup templates and instance with accessor property.
v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
v8::Local<v8::FunctionTemplate> callback =
v8::FunctionTemplate::New(isolate, DoNothingCallback, data);
v8::Local<v8::ObjectTemplate> instance_templ = fun->InstanceTemplate();
instance_templ->SetAccessorProperty(v8_str("accessor"), callback, callback);
Local<Value> test_object =
instance_templ->NewInstance(env.local()).ToLocalChecked();
// Setup global variables.
CHECK(env->Global()
->Set(env.local(), v8_str("test_object"), test_object)
.FromJust());
CompileRun(
"function test() {"
" test_object.accessor;"
"};"
"%PrepareFunctionForOptimization(test);"
"try { test() } catch(e) {}"
"try { test() } catch(e) {}"
"%OptimizeFunctionOnNextCall(test);"
"test()");
}
THREADED_TEST(HulIgennem) { THREADED_TEST(HulIgennem) {
LocalContext env; LocalContext env;
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