[megadom] Add TF inlining for Megadom

The generated code checks if the receiver is a JS_API_OBJECT and if the
receiver requires an access check, and if not it lowers the call to an
API call.

We also add compilation dependencies on the protector cell to deopt if
our invariants change. (Note - the actual invalidation of these cells
will be implemented in a follow up CL)

Bug: v8:11321
Change-Id: I15722f1e5fac7176e292da4a35186e4609636aba
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2719563
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80748}
This commit is contained in:
Maya Lekova 2022-05-25 14:09:42 +02:00 committed by V8 LUCI CQ
parent 51d2256b8a
commit 5480e036d2
23 changed files with 330 additions and 20 deletions

View File

@ -1386,6 +1386,16 @@ Local<FunctionTemplate> FunctionTemplate::New(
return Local<FunctionTemplate>();
}
if (instance_type != 0) {
if (!Utils::ApiCheck(
instance_type >= i::Internals::kFirstJSApiObjectType &&
instance_type <= i::Internals::kLastJSApiObjectType,
"FunctionTemplate::New",
"instance_type is outside the range of valid JSApiObject types.")) {
return Local<FunctionTemplate>();
}
}
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
return FunctionTemplateNew(
i_isolate, callback, data, signature, length, behavior, false,

View File

@ -1064,6 +1064,11 @@ bool CompilationDependencies::DependOnProtector(const PropertyCellRef& cell) {
return true;
}
bool CompilationDependencies::DependOnMegaDOMProtector() {
return DependOnProtector(
MakeRef(broker_, broker_->isolate()->factory()->mega_dom_protector()));
}
bool CompilationDependencies::DependOnArrayBufferDetachingProtector() {
return DependOnProtector(MakeRef(
broker_,

View File

@ -89,6 +89,7 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
bool DependOnPromiseHookProtector();
bool DependOnPromiseSpeciesProtector();
bool DependOnPromiseThenProtector();
bool DependOnMegaDOMProtector();
// Record the assumption that {site}'s {ElementsKind} doesn't change.
void DependOnElementsKind(const AllocationSiteRef& site);

View File

@ -1508,6 +1508,10 @@ bool FunctionTemplateInfoRef::is_signature_undefined() const {
}
HEAP_ACCESSOR_C(FunctionTemplateInfo, bool, accept_any_receiver)
HEAP_ACCESSOR_C(FunctionTemplateInfo, int16_t,
allowed_receiver_instance_type_range_start)
HEAP_ACCESSOR_C(FunctionTemplateInfo, int16_t,
allowed_receiver_instance_type_range_end)
HolderLookupResult FunctionTemplateInfoRef::LookupHolderOfExpectedType(
MapRef receiver_map) {

View File

@ -745,6 +745,9 @@ class FunctionTemplateInfoRef : public HeapObjectRef {
bool is_signature_undefined() const;
bool accept_any_receiver() const;
int16_t allowed_receiver_instance_type_range_start() const;
int16_t allowed_receiver_instance_type_range_end() const;
base::Optional<CallHandlerInfoRef> call_code() const;
ZoneVector<Address> c_functions() const;
ZoneVector<const CFunctionInfo*> c_signatures() const;

View File

@ -20,6 +20,7 @@
#include "src/objects/js-array-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/map-updater.h"
#include "src/objects/megadom-handler-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/oddball.h"
#include "src/objects/property-cell.h"
@ -425,6 +426,12 @@ bool ElementAccessFeedback::HasOnlyStringMaps(JSHeapBroker* broker) const {
return true;
}
MegaDOMPropertyAccessFeedback::MegaDOMPropertyAccessFeedback(
FunctionTemplateInfoRef info_ref, FeedbackSlotKind slot_kind)
: ProcessedFeedback(kMegaDOMPropertyAccess, slot_kind), info_(info_ref) {
DCHECK(IsLoadICKind(slot_kind));
}
NamedAccessFeedback::NamedAccessFeedback(NameRef const& name,
ZoneVector<MapRef> const& maps,
FeedbackSlotKind slot_kind)
@ -510,6 +517,21 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForPropertyAccess(
base::Optional<NameRef> name =
static_name.has_value() ? static_name : GetNameFeedback(nexus);
if (nexus.ic_state() == InlineCacheState::MEGADOM) {
DCHECK(maps.empty());
MaybeObjectHandle maybe_handler = nexus.ExtractMegaDOMHandler();
if (!maybe_handler.is_null()) {
Handle<MegaDomHandler> handler =
Handle<MegaDomHandler>::cast(maybe_handler.object());
if (!handler->accessor(kAcquireLoad)->IsCleared()) {
FunctionTemplateInfoRef info = MakeRefAssumeMemoryFence(
this, FunctionTemplateInfo::cast(
handler->accessor(kAcquireLoad).GetHeapObject()));
return *zone()->New<MegaDOMPropertyAccessFeedback>(info, kind);
}
}
}
// If no maps were found for a non-megamorphic access, then our maps died
// and we should soft-deopt.
if (maps.empty() && nexus.ic_state() != InlineCacheState::MEGAMORPHIC) {
@ -936,6 +958,12 @@ NamedAccessFeedback const& ProcessedFeedback::AsNamedAccess() const {
return *static_cast<NamedAccessFeedback const*>(this);
}
MegaDOMPropertyAccessFeedback const&
ProcessedFeedback::AsMegaDOMPropertyAccess() const {
CHECK_EQ(kMegaDOMPropertyAccess, kind());
return *static_cast<MegaDOMPropertyAccessFeedback const*>(this);
}
LiteralFeedback const& ProcessedFeedback::AsLiteral() const {
CHECK_EQ(kLiteral, kind());
return *static_cast<LiteralFeedback const*>(this);

View File

@ -1037,6 +1037,98 @@ Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) {
}
}
Reduction JSNativeContextSpecialization::ReduceMegaDOMPropertyAccess(
Node* node, Node* value, MegaDOMPropertyAccessFeedback const& feedback,
FeedbackSource const& source) {
DCHECK(node->opcode() == IrOpcode::kJSLoadNamed ||
node->opcode() == IrOpcode::kJSLoadProperty);
// TODO(mslekova): Add support and tests for kJSLoadNamedFromSuper.
static_assert(JSLoadNamedNode::ObjectIndex() == 0 &&
JSLoadPropertyNode::ObjectIndex() == 0,
"Assumptions about ObjectIndex have changed, please update "
"this function.");
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* lookup_start_object = NodeProperties::GetValueInput(node, 0);
if (!dependencies()->DependOnMegaDOMProtector()) {
return NoChange();
}
FunctionTemplateInfoRef function_template_info = feedback.info();
int16_t range_start =
function_template_info.allowed_receiver_instance_type_range_start();
int16_t range_end =
function_template_info.allowed_receiver_instance_type_range_end();
DCHECK_IMPLIES(range_start == 0, range_end == 0);
DCHECK_LE(range_start, range_end);
// TODO(mslekova): This could be a new InstanceTypeCheck operator
// that gets lowered later on (e.g. during generic lowering).
Node* receiver_map = effect =
graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
lookup_start_object, effect, control);
Node* receiver_instance_type = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForMapInstanceType()),
receiver_map, effect, control);
if (FLAG_embedder_instance_types && range_start != 0) {
// Embedder instance ID is set, doing a simple range check.
Node* diff_to_start =
graph()->NewNode(simplified()->NumberSubtract(), receiver_instance_type,
jsgraph()->Constant(range_start));
Node* range_length = jsgraph()->Constant(range_end - range_start);
// TODO(mslekova): Once we have the InstanceTypeCheck operator, we could
// lower it to Uint32LessThan later on to perform what is done in bounds.h.
Node* check = graph()->NewNode(simplified()->NumberLessThanOrEqual(),
diff_to_start, range_length);
effect = graph()->NewNode(
simplified()->CheckIf(DeoptimizeReason::kWrongInstanceType), check,
effect, control);
} else if (function_template_info.is_signature_undefined()) {
// Signature is undefined, enough to check if the receiver is a JSApiObject.
Node* check =
graph()->NewNode(simplified()->NumberEqual(), receiver_instance_type,
jsgraph()->Constant(JS_API_OBJECT_TYPE));
effect = graph()->NewNode(
simplified()->CheckIf(DeoptimizeReason::kWrongInstanceType), check,
effect, control);
} else {
// Calling out to builtin to do signature check.
Callable callable = Builtins::CallableFor(
isolate(), Builtin::kCallFunctionTemplate_CheckCompatibleReceiver);
int stack_arg_count = callable.descriptor().GetStackParameterCount() +
1 /* implicit receiver */;
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
graph()->zone(), callable.descriptor(), stack_arg_count,
CallDescriptor::kNeedsFrameState, Operator::kNoProperties);
Node* inputs[8] = {jsgraph()->HeapConstant(callable.code()),
jsgraph()->Constant(function_template_info),
jsgraph()->Constant(stack_arg_count),
lookup_start_object,
jsgraph()->Constant(native_context()),
frame_state,
effect,
control};
value = effect = control =
graph()->NewNode(common()->Call(call_descriptor), 8, inputs);
return Replace(value);
}
value = InlineApiCall(lookup_start_object, lookup_start_object, frame_state,
nullptr /*value*/, &effect, &control,
function_template_info);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
Reduction JSNativeContextSpecialization::ReduceNamedAccess(
Node* node, Node* value, NamedAccessFeedback const& feedback,
AccessMode access_mode, Node* key) {
@ -2047,6 +2139,11 @@ Reduction JSNativeContextSpecialization::ReducePropertyAccess(
case ProcessedFeedback::kNamedAccess:
return ReduceNamedAccess(node, value, feedback.AsNamedAccess(),
access_mode, key);
case ProcessedFeedback::kMegaDOMPropertyAccess:
DCHECK_EQ(access_mode, AccessMode::kLoad);
DCHECK_NULL(key);
return ReduceMegaDOMPropertyAccess(
node, value, feedback.AsMegaDOMPropertyAccess(), source);
case ProcessedFeedback::kElementAccess:
DCHECK_EQ(feedback.AsElementAccess().keyed_mode().access_mode(),
access_mode);

View File

@ -107,6 +107,9 @@ class V8_EXPORT_PRIVATE JSNativeContextSpecialization final
Reduction ReduceNamedAccess(Node* node, Node* value,
NamedAccessFeedback const& feedback,
AccessMode access_mode, Node* key = nullptr);
Reduction ReduceMegaDOMPropertyAccess(
Node* node, Node* value, MegaDOMPropertyAccessFeedback const& feedback,
FeedbackSource const& source);
Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object,
Node* receiver, Node* value, NameRef const& name,
AccessMode access_mode, Node* key,

View File

@ -20,6 +20,7 @@ class ForInFeedback;
class GlobalAccessFeedback;
class InstanceOfFeedback;
class LiteralFeedback;
class MegaDOMPropertyAccessFeedback;
class NamedAccessFeedback;
class RegExpLiteralFeedback;
class TemplateObjectFeedback;
@ -36,6 +37,7 @@ class ProcessedFeedback : public ZoneObject {
kGlobalAccess,
kInstanceOf,
kLiteral,
kMegaDOMPropertyAccess,
kNamedAccess,
kRegExpLiteral,
kTemplateObject,
@ -53,6 +55,7 @@ class ProcessedFeedback : public ZoneObject {
GlobalAccessFeedback const& AsGlobalAccess() const;
InstanceOfFeedback const& AsInstanceOf() const;
NamedAccessFeedback const& AsNamedAccess() const;
MegaDOMPropertyAccessFeedback const& AsMegaDOMPropertyAccess() const;
LiteralFeedback const& AsLiteral() const;
RegExpLiteralFeedback const& AsRegExpLiteral() const;
TemplateObjectFeedback const& AsTemplateObject() const;
@ -169,6 +172,17 @@ class NamedAccessFeedback : public ProcessedFeedback {
ZoneVector<MapRef> const maps_;
};
class MegaDOMPropertyAccessFeedback : public ProcessedFeedback {
public:
MegaDOMPropertyAccessFeedback(FunctionTemplateInfoRef info_ref,
FeedbackSlotKind slot_kind);
FunctionTemplateInfoRef const& info() const { return info_; }
private:
FunctionTemplateInfoRef const info_;
};
class CallFeedback : public ProcessedFeedback {
public:
CallFeedback(base::Optional<HeapObjectRef> target, float frequency,

View File

@ -1656,6 +1656,14 @@ void PerIsolateData::SetSnapshotObjectCtor(Local<FunctionTemplate> ctor) {
snapshot_object_ctor_.Reset(isolate_, ctor);
}
Local<FunctionTemplate> PerIsolateData::GetDomNodeCtor() const {
return dom_node_ctor_.Get(isolate_);
}
void PerIsolateData::SetDomNodeCtor(Local<FunctionTemplate> ctor) {
dom_node_ctor_.Reset(isolate_, ctor);
}
PerIsolateData::RealmScope::RealmScope(PerIsolateData* data) : data_(data) {
data_->realm_count_ = 1;
data_->realm_current_ = 0;
@ -2992,26 +3000,58 @@ Local<String> Shell::Stringify(Isolate* isolate, Local<Value> value) {
void Shell::NodeTypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
// TODO(mslekova): Enable this once we have signature check in TF.
PerIsolateData* data = PerIsolateData::Get(isolate);
CHECK(data->GetDomNodeCtor()->HasInstance(args.This()));
args.GetReturnValue().Set(v8::Number::New(isolate, 1));
}
Local<FunctionTemplate> Shell::CreateNodeTemplates(Isolate* isolate) {
Local<FunctionTemplate> node = FunctionTemplate::New(isolate);
Local<FunctionTemplate> NewDOMFunctionTemplate(Isolate* isolate,
uint16_t instance_type) {
return FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<Signature>(), 0,
ConstructorBehavior::kAllow, SideEffectType::kHasSideEffect, nullptr,
instance_type);
}
Local<FunctionTemplate> Shell::CreateEventTargetTemplate(Isolate* isolate) {
Local<FunctionTemplate> event_target =
NewDOMFunctionTemplate(isolate, i::Internals::kFirstJSApiObjectType + 1);
return event_target;
}
Local<FunctionTemplate> Shell::CreateNodeTemplates(
Isolate* isolate, Local<FunctionTemplate> event_target) {
Local<FunctionTemplate> node =
NewDOMFunctionTemplate(isolate, i::Internals::kFirstJSApiObjectType + 2);
node->Inherit(event_target);
PerIsolateData* data = PerIsolateData::Get(isolate);
data->SetDomNodeCtor(node);
Local<ObjectTemplate> proto_template = node->PrototypeTemplate();
Local<Signature> signature = v8::Signature::New(isolate, node);
Local<FunctionTemplate> nodeType = FunctionTemplate::New(
isolate, NodeTypeCallback, Local<Value>(), signature);
isolate, NodeTypeCallback, Local<Value>(), signature, 0,
ConstructorBehavior::kThrow, SideEffectType::kHasSideEffect, nullptr,
i::Internals::kFirstJSApiObjectType,
i::Internals::kFirstJSApiObjectType + 3,
i::Internals::kFirstJSApiObjectType + 5);
nodeType->SetAcceptAnyReceiver(false);
proto_template->SetAccessorProperty(
String::NewFromUtf8Literal(isolate, "nodeType"), nodeType);
Local<FunctionTemplate> element = FunctionTemplate::New(isolate);
Local<FunctionTemplate> element =
NewDOMFunctionTemplate(isolate, i::Internals::kFirstJSApiObjectType + 3);
element->Inherit(node);
Local<FunctionTemplate> html_element = FunctionTemplate::New(isolate);
Local<FunctionTemplate> html_element =
NewDOMFunctionTemplate(isolate, i::Internals::kFirstJSApiObjectType + 4);
html_element->Inherit(element);
Local<FunctionTemplate> div_element = FunctionTemplate::New(isolate);
Local<FunctionTemplate> div_element =
NewDOMFunctionTemplate(isolate, i::Internals::kFirstJSApiObjectType + 5);
div_element->Inherit(html_element);
return div_element;
@ -3210,7 +3250,11 @@ Local<ObjectTemplate> Shell::CreateD8Template(Isolate* isolate) {
}
{
Local<ObjectTemplate> dom_template = ObjectTemplate::New(isolate);
dom_template->Set(isolate, "Div", Shell::CreateNodeTemplates(isolate));
Local<FunctionTemplate> event_target =
Shell::CreateEventTargetTemplate(isolate);
dom_template->Set(isolate, "EventTarget", event_target);
dom_template->Set(isolate, "Div",
Shell::CreateNodeTemplates(isolate, event_target));
d8_template->Set(isolate, "dom", dom_template);
}
{

View File

@ -324,6 +324,9 @@ class PerIsolateData {
Local<FunctionTemplate> GetSnapshotObjectCtor() const;
void SetSnapshotObjectCtor(Local<FunctionTemplate> ctor);
Local<FunctionTemplate> GetDomNodeCtor() const;
void SetDomNodeCtor(Local<FunctionTemplate> ctor);
private:
friend class Shell;
friend class RealmScope;
@ -344,6 +347,7 @@ class PerIsolateData {
#endif
Global<FunctionTemplate> test_api_object_ctor_;
Global<FunctionTemplate> snapshot_object_ctor_;
Global<FunctionTemplate> dom_node_ctor_;
int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
int arg_offset);
@ -741,7 +745,9 @@ class Shell : public i::AllStatic {
static void NodeTypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args);
static Local<FunctionTemplate> CreateNodeTemplates(Isolate* isolate);
static Local<FunctionTemplate> CreateEventTargetTemplate(Isolate* isolate);
static Local<FunctionTemplate> CreateNodeTemplates(
Isolate* isolate, Local<FunctionTemplate> event_target);
static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
static Local<ObjectTemplate> CreateOSTemplate(Isolate* isolate);
static Local<FunctionTemplate> CreateWorkerTemplate(Isolate* isolate);

View File

@ -3527,7 +3527,7 @@ Handle<MegaDomHandler> Factory::NewMegaDomHandler(MaybeObjectHandle accessor,
Handle<Map> map = read_only_roots().mega_dom_handler_map_handle();
MegaDomHandler handler = MegaDomHandler::cast(New(map, AllocationType::kOld));
DisallowGarbageCollection no_gc;
handler.set_accessor(*accessor);
handler.set_accessor(*accessor, kReleaseStore);
handler.set_context(*context);
return handle(handler, isolate());
}

View File

@ -642,9 +642,16 @@ bool IC::UpdateMegaDOMIC(const MaybeObjectHandle& handler, Handle<Name> name) {
Handle<Context> accessor_context(call_optimization.GetAccessorContext(*map),
isolate());
Handle<FunctionTemplateInfo> fti;
if (accessor_obj->IsJSFunction()) {
fti = handle(JSFunction::cast(*accessor_obj).shared().get_api_func_data(),
isolate());
} else {
fti = Handle<FunctionTemplateInfo>::cast(accessor_obj);
}
Handle<MegaDomHandler> new_handler = isolate()->factory()->NewMegaDomHandler(
MaybeObjectHandle::Weak(accessor_obj),
MaybeObjectHandle::Weak(accessor_context));
MaybeObjectHandle::Weak(fti), MaybeObjectHandle::Weak(accessor_context));
nexus()->ConfigureMegaDOM(MaybeObjectHandle(new_handler));
return true;
}

View File

@ -1089,6 +1089,20 @@ int FeedbackNexus::ExtractMapsAndFeedback(
return found;
}
MaybeObjectHandle FeedbackNexus::ExtractMegaDOMHandler() {
DCHECK(ic_state() == InlineCacheState::MEGADOM);
DisallowGarbageCollection no_gc;
auto pair = GetFeedbackPair();
MaybeObject maybe_handler = pair.second;
if (!maybe_handler->IsCleared()) {
MaybeObjectHandle handler = config()->NewHandle(maybe_handler);
return handler;
}
return MaybeObjectHandle();
}
int FeedbackNexus::ExtractMapsAndHandlers(
std::vector<MapAndHandler>* maps_and_handlers,
TryUpdateHandler map_handler) const {

View File

@ -818,6 +818,7 @@ class V8_EXPORT_PRIVATE FeedbackNexus final {
Handle<Name> name, std::vector<MapAndHandler> const& maps_and_handlers);
void ConfigureMegaDOM(const MaybeObjectHandle& handler);
MaybeObjectHandle ExtractMegaDOMHandler();
BinaryOperationHint GetBinaryOperationFeedback() const;
CompareOperationHint GetCompareOperationFeedback() const;

View File

@ -18,6 +18,8 @@ namespace internal {
TQ_OBJECT_CONSTRUCTORS_IMPL(MegaDomHandler)
RELEASE_ACQUIRE_WEAK_ACCESSORS(MegaDomHandler, accessor, kAccessorOffset)
} // namespace internal
} // namespace v8

View File

@ -21,6 +21,8 @@ class MegaDomHandler
void BriefPrintDetails(std::ostream& os);
class BodyDescriptor;
DECL_RELEASE_ACQUIRE_WEAK_ACCESSORS(accessor)
TQ_OBJECT_CONSTRUCTORS(MegaDomHandler)
};

View File

@ -178,6 +178,11 @@ bool ComparisonResultToBool(Operation op, ComparisonResult result) {
}
std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
if (InstanceTypeChecker::IsJSApiObject(instance_type)) {
return os << "[api object] "
<< static_cast<int16_t>(instance_type) -
i::Internals::kFirstJSApiObjectType;
}
switch (instance_type) {
#define WRITE_TYPE(TYPE) \
case TYPE: \
@ -2133,7 +2138,7 @@ void Tuple2::BriefPrintDetails(std::ostream& os) {
}
void MegaDomHandler::BriefPrintDetails(std::ostream& os) {
os << " " << Brief(accessor()) << ", " << Brief(context());
os << " " << Brief(accessor(kAcquireLoad)) << ", " << Brief(context());
}
void ClassPositions::BriefPrintDetails(std::ostream& os) {

View File

@ -29366,26 +29366,29 @@ TEST(EmbedderInstanceTypes) {
Local<FunctionTemplate> nodeType = v8::FunctionTemplate::New(
isolate, NodeTypeCallback, Local<Value>(),
v8::Signature::New(isolate, node), 0, v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, nullptr, 0, 1, 3);
v8::SideEffectType::kHasSideEffect, nullptr,
i::Internals::kFirstJSApiObjectType,
i::Internals::kFirstJSApiObjectType + 1,
i::Internals::kFirstJSApiObjectType + 3);
proto_template->SetAccessorProperty(
String::NewFromUtf8Literal(isolate, "nodeType"), nodeType);
Local<FunctionTemplate> element = FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
nullptr, 1);
nullptr, i::Internals::kFirstJSApiObjectType + 1);
element->Inherit(node);
Local<FunctionTemplate> html_element = FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
nullptr, 2);
nullptr, i::Internals::kFirstJSApiObjectType + 2);
html_element->Inherit(element);
Local<FunctionTemplate> div_element = FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
nullptr, 3);
nullptr, i::Internals::kFirstJSApiObjectType + 3);
div_element->Inherit(html_element);
CHECK(env->Global()

View File

@ -4,6 +4,9 @@
//
// Flags: --enable-mega-dom-ic --allow-natives-syntax
// This tests checks that load property access using megadom IC returns
// correct results both on API objects and plain JS objects.
function load(obj) {
return obj.nodeType;
}
@ -30,7 +33,6 @@ const objs = [
a, b, c, d, e, f
];
function test() {
let result = 0;
for (let i = 0; i < objs.length; i++) {
@ -49,4 +51,4 @@ assertEquals(load({ nodeType: 'foo' }), 'foo');
result = test();
assertEquals(6, result);
assertEquals(load({}), undefined)
assertEquals(load({nodeType: 'foo'}), 'foo')
assertEquals(load({nodeType: 'foo'}), 'foo');

View File

@ -0,0 +1,57 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --enable-mega-dom-ic --allow-natives-syntax
// This tests checks that load property access using megadom IC
// handles correctly the error of signature mismatch.
function load(obj) {
return obj.nodeType;
}
%PrepareFunctionForOptimization(load);
let a = new d8.dom.Div();
let b = new d8.dom.Div();
b.b = 1;
let c = new d8.dom.Div();
c.c = 1;
let d = new d8.dom.Div();
d.d = 1;
let e = new d8.dom.Div();
e.e = 1;
let f = new d8.dom.Div();
f.f = 1;
const objs = [
a, b, c, d, e, f
];
function test() {
let result = 0;
for (let i = 0; i < objs.length; i++) {
result += load(objs[i]);
}
try {
load(new d8.dom.EventTarget());
} catch (err) {
assertInstanceof(err, TypeError);
assertEquals("Illegal invocation", err.message, 'Error message');
}
return result;
}
%PrepareFunctionForOptimization(test);
let result = test();
assertEquals(6, result);
%OptimizeFunctionOnNextCall(test);
result = test();
assertEquals(6, result);

View File

@ -4,6 +4,9 @@
//
// Flags: --enable-mega-dom-ic --allow-natives-syntax
// This tests checks that load property access using megadom IC returns
// correct results on API.
function load(obj) {
return obj.nodeType;
}
@ -29,8 +32,6 @@ const objs = [
a, b, c, d, e, f
];
function test() {
let result = 0;
for (let i = 0; i < objs.length; i++) {

View File

@ -345,6 +345,7 @@ header = '''
#include "src/objects/data-handler.h"
#include "src/objects/js-promise.h"
#include "src/objects/js-regexp-string-iterator.h"
#include "src/objects/megadom-handler.h"
namespace v8 {
namespace internal {