зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1896505 - Track Type III Subclassing in RegExp r=jandem
The challenge of getting this right is truly comical. Differential Revision: https://phabricator.services.mozilla.com/D211457
This commit is contained in:
Родитель
ca21ea9219
Коммит
b40d7d5990
|
@ -78,6 +78,7 @@ custom JS_subclassing_typedarray_type_2 TypedArray is Type II subclassed
|
|||
custom JS_subclassing_typedarray_type_3 TypedArray is Type III subclassed
|
||||
custom JS_subclassing_arraybuffer_type_3 ArrayBuffer is Type III subclassed
|
||||
custom JS_subclassing_sharedarraybuffer_type_3 SharedArrayBuffer is Type III subclassed
|
||||
custom JS_subclassing_regexp_type_3 RegExp is Type III subclassed
|
||||
|
||||
// Console API
|
||||
method console.assert
|
||||
|
|
|
@ -107,8 +107,8 @@ use.counter:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 2325 use counter metrics (excludes denominators).
|
||||
# Total of 362 'page' use counters.
|
||||
# Total of 2327 use counter metrics (excludes denominators).
|
||||
# Total of 363 'page' use counters.
|
||||
use.counter.page:
|
||||
svgsvgelement_getelementbyid:
|
||||
type: counter
|
||||
|
@ -671,6 +671,23 @@ use.counter.page:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
js_subclassing_regexp_type_3:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a page RegExp is Type III subclassed.
|
||||
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
console_assert:
|
||||
type: counter
|
||||
description: >
|
||||
|
@ -6264,7 +6281,7 @@ use.counter.page:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 362 'document' use counters.
|
||||
# Total of 363 'document' use counters.
|
||||
use.counter.doc:
|
||||
svgsvgelement_getelementbyid:
|
||||
type: counter
|
||||
|
@ -6827,6 +6844,23 @@ use.counter.doc:
|
|||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
js_subclassing_regexp_type_3:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a document RegExp is Type III subclassed.
|
||||
Compare against `use.counter.content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
console_assert:
|
||||
type: counter
|
||||
description: >
|
||||
|
|
|
@ -95,7 +95,9 @@ extern JS_PUBLIC_API void JS_SetAccumulateTelemetryCallback(
|
|||
_(SUBCLASSING_TYPEDARRAY_TYPE_II, SubclassingTypedArrayTypeII) \
|
||||
_(SUBCLASSING_TYPEDARRAY_TYPE_III, SubclassingTypedArrayTypeIII) \
|
||||
_(SUBCLASSING_ARRAYBUFFER_TYPE_III, SubclassingArrayBufferTypeIII) \
|
||||
_(SUBCLASSING_SHAREDARRAYBUFFER_TYPE_III, SubclassingSharedArrayBufferTypeIII)
|
||||
_(SUBCLASSING_SHAREDARRAYBUFFER_TYPE_III, \
|
||||
SubclassingSharedArrayBufferTypeIII) \
|
||||
_(SUBCLASSING_REGEXP_TYPE_III, SubclassingRegExpTypeIII)
|
||||
|
||||
/*
|
||||
* Use counter names passed to the accumulate use counter callback.
|
||||
|
|
|
@ -135,7 +135,8 @@
|
|||
#define SUBCLASSING_TYPEDARRAY 3
|
||||
#define SUBCLASSING_ARRAYBUFFER 4
|
||||
#define SUBCLASSING_SHAREDARRAYBUFFER 5
|
||||
#define SUBCLASSING_LAST_BUILTIN 6
|
||||
#define SUBCLASSING_REGEXP 6
|
||||
#define SUBCLASSING_LAST_BUILTIN 7
|
||||
|
||||
#define SUBCLASSING_TYPE_II 2
|
||||
#define SUBCLASSING_TYPE_III 3
|
||||
|
@ -158,4 +159,7 @@
|
|||
|
||||
#define SUBCLASSING_DETERMINE_THROUGH_CONSTRUCTOR_TYPE_III SUBCLASSING_TYPE_III
|
||||
|
||||
#define SUBCLASS_REGEXP_TYPE_III \
|
||||
((SUBCLASSING_REGEXP << SUBCLASSING_BUILTIN_SHIFT) | SUBCLASSING_TYPE_III)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
function test_function_for_use_counter_integration(fn, counter, expected_growth = true) {
|
||||
let before = getUseCounterResults();
|
||||
assertEq(counter in before, true);
|
||||
|
||||
fn();
|
||||
|
||||
let after = getUseCounterResults();
|
||||
if (expected_growth) {
|
||||
console.log("Yes Increase: Before ", before[counter], " After", after[counter]);
|
||||
assertEq(after[counter] > before[counter], true);
|
||||
} else {
|
||||
console.log("No Increase: Before ", before[counter], " After", after[counter]);
|
||||
assertEq(after[counter] == before[counter], true);
|
||||
}
|
||||
}
|
||||
|
||||
function R() { }
|
||||
Object.setPrototypeOf(R, RegExp);
|
||||
Object.setPrototypeOf(R.prototype, RegExp.prototype);
|
||||
|
||||
// Define a bunch of new getters since the builtin getters throw on
|
||||
// non-RegExp-branded `this`
|
||||
Object.defineProperty(R.prototype, "hasIndices", { value: false });
|
||||
Object.defineProperty(R.prototype, "global", { value: true });
|
||||
Object.defineProperty(R.prototype, "ignoreCase", { value: false });
|
||||
Object.defineProperty(R.prototype, "multiline", { value: false });
|
||||
Object.defineProperty(R.prototype, "dotAll", { value: false });
|
||||
Object.defineProperty(R.prototype, "unicode", { value: false });
|
||||
Object.defineProperty(R.prototype, "unicodeSets", { value: false });
|
||||
Object.defineProperty(R.prototype, "sticky", { value: false });
|
||||
|
||||
function test_regexp_matchall() {
|
||||
"some".matchAll(/foo/g);
|
||||
}
|
||||
|
||||
function test_regexp_matchall_type_iii() {
|
||||
"some string".matchAll(new R("foo"))
|
||||
}
|
||||
|
||||
test_function_for_use_counter_integration(test_regexp_matchall, "SubclassingRegExpTypeIII", false)
|
||||
test_function_for_use_counter_integration(test_regexp_matchall_type_iii, "SubclassingRegExpTypeIII", true)
|
||||
|
||||
function test_regexp_split() {
|
||||
let r = /p/;
|
||||
let split = r[Symbol.split];
|
||||
split.call(r, "split");
|
||||
}
|
||||
|
||||
function test_regexp_split_type_iii() {
|
||||
let r = /r/;
|
||||
|
||||
class B extends RegExp {
|
||||
x = "this";
|
||||
}
|
||||
|
||||
let b = new B("R");
|
||||
|
||||
let split = r[Symbol.split];
|
||||
|
||||
// This reciever needs to be a class-subclass RegExp,
|
||||
// as RegExp[@@split] will call RegExp.exec, which
|
||||
// typechecks this.
|
||||
split.call(b, "split");
|
||||
}
|
||||
|
||||
|
||||
|
||||
test_function_for_use_counter_integration(test_regexp_split, "SubclassingRegExpTypeIII", false)
|
||||
test_function_for_use_counter_integration(test_regexp_split_type_iii, "SubclassingRegExpTypeIII", true)
|
|
@ -605,6 +605,14 @@ class GlobalObject : public NativeObject {
|
|||
return &global->getPrototype(JSProto_RegExp);
|
||||
}
|
||||
|
||||
static JSObject* getOrCreateRegExpConstructor(JSContext* cx,
|
||||
Handle<GlobalObject*> global) {
|
||||
if (!ensureConstructor(cx, global, JSProto_RegExp)) {
|
||||
return nullptr;
|
||||
}
|
||||
return &global->getConstructor(JSProto_RegExp);
|
||||
}
|
||||
|
||||
JSObject* maybeGetRegExpPrototype() {
|
||||
if (classIsInitialized(JSProto_RegExp)) {
|
||||
return &getPrototype(JSProto_RegExp);
|
||||
|
|
|
@ -2970,17 +2970,25 @@ bool js::ReportUsageCounter(JSContext* cx, HandleObject constructorArg,
|
|||
// Do this here rather than as part of the self-hosted code.
|
||||
if (builtin == SUBCLASSING_DETERMINE_THROUGH_CONSTRUCTOR) {
|
||||
MOZ_ASSERT(constructor);
|
||||
if (IsPromiseConstructor(constructor)) {
|
||||
builtin = SUBCLASSING_PROMISE;
|
||||
} else if (IsTypedArrayConstructor(constructor)) {
|
||||
builtin = SUBCLASSING_TYPEDARRAY;
|
||||
} else if (IsArrayConstructor(constructor)) {
|
||||
builtin = SUBCLASSING_ARRAY;
|
||||
} else {
|
||||
|
||||
do {
|
||||
if (IsPromiseConstructor(constructor)) {
|
||||
builtin = SUBCLASSING_PROMISE;
|
||||
break;
|
||||
}
|
||||
if (IsTypedArrayConstructor(constructor)) {
|
||||
builtin = SUBCLASSING_TYPEDARRAY;
|
||||
break;
|
||||
}
|
||||
if (IsArrayConstructor(constructor)) {
|
||||
builtin = SUBCLASSING_ARRAY;
|
||||
break;
|
||||
}
|
||||
if (IsCrossCompartmentWrapper(constructor)) {
|
||||
// Bail on reporting CCWs.
|
||||
return true;
|
||||
}
|
||||
|
||||
Rooted<GlobalObject*> global(cx, &constructor->nonCCWGlobal());
|
||||
RootedObject abConstructor(
|
||||
cx, GlobalObject::getOrCreateArrayBufferConstructor(cx, global));
|
||||
|
@ -2989,21 +2997,35 @@ bool js::ReportUsageCounter(JSContext* cx, HandleObject constructorArg,
|
|||
}
|
||||
if (constructor == abConstructor) {
|
||||
builtin = SUBCLASSING_ARRAYBUFFER;
|
||||
} else {
|
||||
RootedObject sabConstructor(
|
||||
cx,
|
||||
GlobalObject::getOrCreateSharedArrayBufferConstructor(cx, global));
|
||||
if (!sabConstructor) {
|
||||
return false;
|
||||
}
|
||||
if (constructor == sabConstructor) {
|
||||
builtin = SUBCLASSING_SHAREDARRAYBUFFER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// While we still have builtins to process, return true here.
|
||||
RootedObject sabConstructor(
|
||||
cx,
|
||||
GlobalObject::getOrCreateSharedArrayBufferConstructor(cx, global));
|
||||
if (!sabConstructor) {
|
||||
return false;
|
||||
}
|
||||
if (constructor == sabConstructor) {
|
||||
builtin = SUBCLASSING_SHAREDARRAYBUFFER;
|
||||
break;
|
||||
}
|
||||
|
||||
RootedObject regExpConstructor(
|
||||
cx, GlobalObject::getOrCreateRegExpConstructor(cx, global));
|
||||
if (!regExpConstructor) {
|
||||
return false;
|
||||
}
|
||||
if (constructor == regExpConstructor) {
|
||||
builtin = SUBCLASSING_REGEXP;
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
// We should have determined the constructor here.
|
||||
if (builtin == SUBCLASSING_DETERMINE_THROUGH_CONSTRUCTOR) {
|
||||
MOZ_CRASH("Unable to determine constructor where expected.");
|
||||
return true;
|
||||
}
|
||||
// We -do- want to report here, because we've determined exterior to this
|
||||
|
@ -3083,6 +3105,16 @@ bool js::ReportUsageCounter(JSContext* cx, HandleObject constructorArg,
|
|||
: JSUseCounter::SUBCLASSING_SHAREDARRAYBUFFER_TYPE_III);
|
||||
return true;
|
||||
}
|
||||
case SUBCLASSING_REGEXP: {
|
||||
switch (type) {
|
||||
case SUBCLASSING_TYPE_III:
|
||||
cx->runtime()->setUseCounter(
|
||||
cx->global(), JSUseCounter::SUBCLASSING_REGEXP_TYPE_III);
|
||||
return true;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected RegExp Subclassing Type");
|
||||
}
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("Unexpected builtin");
|
||||
};
|
||||
|
|
|
@ -2668,6 +2668,10 @@ static void SetUseCounterCallback(JSObject* obj, JSUseCounter counter) {
|
|||
obj,
|
||||
mozilla::eUseCounter_custom_JS_subclassing_sharedarraybuffer_type_3);
|
||||
return;
|
||||
case JSUseCounter::SUBCLASSING_REGEXP_TYPE_III:
|
||||
SetUseCounter(obj,
|
||||
mozilla::eUseCounter_custom_JS_subclassing_regexp_type_3);
|
||||
return;
|
||||
case JSUseCounter::COUNT:
|
||||
break;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче