#392: prerequisite SetCanonicalName M1235656 M1236638

This commit is contained in:
Cameron Kaiser 2018-09-29 21:32:12 -07:00
parent 3920907ee4
commit c1f84d6285
15 changed files with 172 additions and 42 deletions

View File

@ -732,6 +732,7 @@ function ArrayValuesAt(n) {
function ArrayValues() {
return CreateArrayIterator(this, ITEM_KIND_VALUE);
}
_SetCanonicalName(ArrayValues, "values");
function ArrayEntries() {
return CreateArrayIterator(this, ITEM_KIND_KEY_AND_VALUE);

View File

@ -88,6 +88,7 @@ function LegacyGeneratorNext(val) {
throw e;
}
}
_SetCanonicalName(LegacyGeneratorNext, "next");
function LegacyGeneratorThrow(val) {
if (!IsObject(this) || !IsLegacyGeneratorObject(this))

View File

@ -100,8 +100,8 @@ function removeUnicodeExtensions(locale) {
if (pos < 0)
pos = locale.length;
var left = callFunction(std_String_substring, locale, 0, pos);
var right = callFunction(std_String_substring, locale, pos);
var left = callFunction(String_substring, locale, 0, pos);
var right = callFunction(String_substring, locale, pos);
var extensions;
var unicodeLocaleExtensionSequenceRE = getUnicodeLocaleExtensionSequenceRE();
@ -332,7 +332,7 @@ function IsStructurallyValidLanguageTag(locale) {
return true;
var pos = callFunction(std_String_indexOf, locale, "-x-");
if (pos !== -1)
locale = callFunction(std_String_substring, locale, 0, pos);
locale = callFunction(String_substring, locale, 0, pos);
// Check for duplicate variant or singleton subtags.
var duplicateVariantRE = getDuplicateVariantRE();
@ -401,7 +401,7 @@ function CanonicalizeLanguageTag(locale) {
// 4-character subtags are script codes; their first character
// needs to be capitalized. "hans" -> "Hans"
subtag = callFunction(std_String_toUpperCase, subtag[0]) +
callFunction(std_String_substring, subtag, 1);
callFunction(String_substring, subtag, 1);
} else if (i !== 0 && subtag.length === 2) {
// 2-character subtags that are not in initial position are region
// codes; they need to be upper case. "bu" -> "BU"
@ -678,7 +678,7 @@ function CanonicalizeLocaleList(locales) {
if (!IsStructurallyValidLanguageTag(tag))
ThrowRangeError(JSMSG_INVALID_LANGUAGE_TAG, tag);
tag = CanonicalizeLanguageTag(tag);
if (callFunction(std_Array_indexOf, seen, tag) === -1)
if (callFunction(ArrayIndexOf, seen, tag) === -1)
callFunction(std_Array_push, seen, tag);
}
k++;
@ -726,7 +726,7 @@ function BestAvailableLocaleHelper(availableLocales, locale, considerDefaultLoca
if (pos >= 2 && candidate[pos - 2] === "-")
pos -= 2;
candidate = callFunction(std_String_substring, candidate, 0, pos);
candidate = callFunction(String_substring, candidate, 0, pos);
}
}
@ -879,7 +879,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// Step 11.g.
if (extensionSubtags !== undefined) {
// Step 11.g.i.
var keyPos = callFunction(std_Array_indexOf, extensionSubtags, key);
var keyPos = callFunction(ArrayIndexOf, extensionSubtags, key);
// Step 11.g.ii.
if (keyPos !== -1) {
@ -891,7 +891,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
var requestedValue = extensionSubtags[keyPos + 1];
// Step 11.g.ii.1.b.
valuePos = callFunction(std_Array_indexOf, keyLocaleData, requestedValue);
valuePos = callFunction(ArrayIndexOf, keyLocaleData, requestedValue);
// Step 11.g.ii.1.c.
if (valuePos !== -1) {
@ -905,7 +905,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// and true is an allowed value, it's used.
// Step 11.g.ii.2.a.
valuePos = callFunction(std_Array_indexOf, keyLocaleData, "true");
valuePos = callFunction(ArrayIndexOf, keyLocaleData, "true");
// Step 11.g.ii.2.b.
if (valuePos !== -1)
@ -921,7 +921,7 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// Step 11.h, 11.h.ii.
if (optionsValue !== undefined &&
callFunction(std_Array_indexOf, keyLocaleData, optionsValue) !== -1)
callFunction(ArrayIndexOf, keyLocaleData, optionsValue) !== -1)
{
// Step 11.h.ii.1.
if (optionsValue !== value) {
@ -938,8 +938,8 @@ function ResolveLocale(availableLocales, requestedLocales, options, relevantExte
// Step 12.
if (supportedExtension.length > 2) {
var preExtension = callFunction(std_String_substring, foundLocale, 0, extensionIndex);
var postExtension = callFunction(std_String_substring, foundLocale, extensionIndex);
var preExtension = callFunction(String_substring, foundLocale, 0, extensionIndex);
var postExtension = callFunction(String_substring, foundLocale, extensionIndex);
foundLocale = preExtension + supportedExtension + postExtension;
}
@ -1060,7 +1060,7 @@ function GetOption(options, property, type, values, fallback) {
assert(false, "GetOption");
// Step 2.d.
if (values !== undefined && callFunction(std_Array_indexOf, values, value) === -1)
if (values !== undefined && callFunction(ArrayIndexOf, values, value) === -1)
ThrowRangeError(JSMSG_INVALID_OPTION_VALUE, property, value);
// Step 2.e.
@ -2612,8 +2612,8 @@ function BasicFormatMatcher(options, formats) {
score -= removalPenalty;
} else {
// Step 11.c.vi.
var optionsPropIndex = callFunction(std_Array_indexOf, values, optionsProp);
var formatPropIndex = callFunction(std_Array_indexOf, values, formatProp);
var optionsPropIndex = callFunction(ArrayIndexOf, values, optionsProp);
var formatPropIndex = callFunction(ArrayIndexOf, values, formatProp);
var delta = std_Math_max(std_Math_min(formatPropIndex - optionsPropIndex, 2), -2);
if (delta === 2)
score -= longMorePenalty;

View File

@ -25,7 +25,7 @@ function MapForEach(callbackfn, thisArg = undefined) {
/* Step 6-8. */
var entries = callFunction(std_Map_iterator, M);
while (true) {
var result = callFunction(std_Map_iterator_next, entries);
var result = callFunction(MapIteratorNext, entries);
if (result.done)
break;
var entry = result.value;
@ -88,3 +88,4 @@ function MapSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(MapSpecies, "get [Symbol.species]");

View File

@ -35,6 +35,7 @@ function RegExpFlagsGetter() {
// Step 19.
return result;
}
_SetCanonicalName(RegExpFlagsGetter, "get flags");
// ES6 draft rc1 21.2.5.14.
function RegExpToString()
@ -53,3 +54,4 @@ function RegExpToString()
// Step 7.
return '/' + pattern + '/' + flags;
}
_SetCanonicalName(RegExpToString, "toString");

View File

@ -34,6 +34,11 @@
// stored.
#define LAZY_FUNCTION_NAME_SLOT 0
// The extended slot which contains a boolean value that indicates whether
// that the canonical name of the self-hosted builtins is set in self-hosted
// global. This slot is used only in debug build.
#define HAS_SELFHOSTED_CANONICAL_NAME_SLOT 0
// Stores the private WeakMap slot used for WeakSets
#define WEAKSET_MAP_SLOT 0

View File

@ -38,3 +38,4 @@ function SetSpecies() {
// Step 1.
return this;
}
_SetCanonicalName(SetSpecies, "get [Symbol.species]");

View File

@ -277,7 +277,7 @@ function StringIteratorNext() {
}
UnsafeSetReservedSlot(this, ITERATOR_SLOT_NEXT_INDEX, index + charCount);
result.value = callFunction(std_String_substring, S, index, index + charCount);
result.value = callFunction(String_substring, S, index, index + charCount);
return result;
}
@ -482,14 +482,14 @@ function EscapeAttributeValue(v) {
var chunkStart = 0;
for (var i = 0; i < inputLen; i++) {
if (inputStr[i] === '"') {
outputStr += callFunction(std_String_substring, inputStr, chunkStart, i) + '&quot;';
outputStr += callFunction(String_substring, inputStr, chunkStart, i) + '&quot;';
chunkStart = i + 1;
}
}
if (chunkStart === 0)
return inputStr;
if (chunkStart < inputLen)
outputStr += callFunction(std_String_substring, inputStr, chunkStart);
outputStr += callFunction(String_substring, inputStr, chunkStart);
return outputStr;
}

View File

@ -964,6 +964,7 @@ function TypedArrayValues() {
// Step 7.
return CreateArrayIterator(O, ITEM_KIND_VALUE);
}
_SetCanonicalName(TypedArrayValues, "values");
// Proposed for ES7:
// https://github.com/tc39/Array.prototype.includes/blob/7c023c19a0/spec.md

View File

@ -36,15 +36,13 @@
// code are installed via the std_functions JSFunctionSpec[] in
// SelfHosting.cpp.
//
// The few items below here are either self-hosted or installing them under a
// std_Foo name would require ugly contortions, so they just get aliased here.
var std_Array_indexOf = ArrayIndexOf;
var std_String_substring = String_substring;
// Do not create an alias to a self-hosted builtin, otherwise it will be cloned
// twice.
//
// WeakMap is a bare constructor without properties or methods.
var std_WeakMap = WeakMap;
// StopIteration is a bare constructor without properties or methods.
var std_StopIteration = StopIteration;
var std_Map_iterator_next = MapIteratorNext;
/********** List specification type **********/

View File

@ -30,6 +30,7 @@
#include "asmjs/AsmJSValidate.h"
#include "builtin/ModuleObject.h"
#include "builtin/SelfHostingDefines.h"
#include "frontend/BytecodeCompiler.h"
#include "frontend/FoldConstants.h"
#include "frontend/ParseMaps.h"
@ -1619,6 +1620,9 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
JSFunction::Flags flags;
#ifdef DEBUG
bool isGlobalSelfHostedBuiltin = false;
#endif
switch (kind) {
case Expression:
flags = (generatorKind == NotGenerator
@ -1652,6 +1656,13 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
break;
default:
MOZ_ASSERT(kind == Statement);
#ifdef DEBUG
if (options().selfHostingMode && !pc->sc->isFunctionBox()) {
isGlobalSelfHostedBuiltin = true;
allocKind = gc::AllocKind::FUNCTION_EXTENDED;
}
#endif
flags = (generatorKind == NotGenerator
? JSFunction::INTERPRETED_NORMAL
: JSFunction::INTERPRETED_GENERATOR);
@ -1661,8 +1672,13 @@ Parser<ParseHandler>::newFunction(HandleAtom atom, FunctionSyntaxKind kind,
allocKind, TenuredObject);
if (!fun)
return nullptr;
if (options().selfHostingMode)
if (options().selfHostingMode) {
fun->setIsSelfHostedBuiltin();
#ifdef DEBUG
if (isGlobalSelfHostedBuiltin)
fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(false));
#endif
}
return fun;
}

View File

@ -306,6 +306,8 @@ class JSFunction : public js::NativeObject
void initAtom(JSAtom* atom) { atom_.init(atom); }
void setAtom(JSAtom* atom) { atom_ = atom; }
JSAtom* displayAtom() const {
return atom_;
}

View File

@ -658,16 +658,37 @@ GlobalObject::getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global,
HandlePropertyName selfHostedName, HandleAtom name,
unsigned nargs, MutableHandleValue funVal)
{
if (GlobalObject::maybeGetIntrinsicValue(cx, global, selfHostedName, funVal))
return true;
if (GlobalObject::maybeGetIntrinsicValue(cx, global, selfHostedName, funVal)) {
RootedFunction fun(cx, &funVal.toObject().as<JSFunction>());
if (fun->atom() == name)
return true;
JSFunction* fun =
NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
name, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
if (!fun)
if (fun->atom() == selfHostedName) {
// This function was initially cloned because it was called by
// other self-hosted code, so the clone kept its self-hosted name,
// instead of getting the name it's intended to have in content
// compartments. This can happen when a lazy builtin is initialized
// after self-hosted code for another builtin used the same
// function. In that case, we need to change the function's name,
// which is ok because it can't have been exposed to content
// before.
fun->initAtom(name);
return true;
}
// The function might be installed multiple times on the same or
// different builtins, under different property names, so its name
// might be neither "selfHostedName" nor "name". In that case, its
// canonical name must've been set using the `_SetCanonicalName`
// intrinsic.
cx->runtime()->assertSelfHostedFunctionHasCanonicalName(cx, selfHostedName);
return true;
}
RootedFunction fun(cx);
if (!cx->runtime()->createLazySelfHostedFunctionClone(cx, selfHostedName, name, nargs, &fun))
return false;
fun->setIsSelfHostedBuiltin();
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
funVal.setObject(*fun);
return GlobalObject::addIntrinsicValue(cx, global, selfHostedName, funVal);

View File

@ -934,6 +934,10 @@ struct JSRuntime : public JS::shadow::Runtime,
static js::GlobalObject*
createSelfHostingGlobal(JSContext* cx);
bool getUnclonedSelfHostedValue(JSContext* cx, js::HandlePropertyName name,
js::MutableHandleValue vp);
JSFunction* getUnclonedSelfHostedFunction(JSContext* cx, js::HandlePropertyName name);
/* Space for interpreter frames. */
js::InterpreterStack interpreterStack_;
@ -974,10 +978,14 @@ struct JSRuntime : public JS::shadow::Runtime,
}
bool isSelfHostingCompartment(JSCompartment* comp) const;
bool isSelfHostingZone(const JS::Zone* zone) const;
bool createLazySelfHostedFunctionClone(JSContext* cx, js::HandlePropertyName selfHostedName,
js::HandleAtom name, unsigned nargs,
js::MutableHandleFunction fun);
bool cloneSelfHostedFunctionScript(JSContext* cx, js::Handle<js::PropertyName*> name,
js::Handle<JSFunction*> targetFun);
bool cloneSelfHostedValue(JSContext* cx, js::Handle<js::PropertyName*> name,
js::MutableHandleValue vp);
void assertSelfHostedFunctionHasCanonicalName(JSContext* cx, js::HandlePropertyName name);
//-------------------------------------------------------------------------
// Locale information

View File

@ -15,6 +15,7 @@
#include "jscompartment.h"
#include "jsdate.h"
#include "jsfriendapi.h"
#include "jsfun.h"
#include "jshashutil.h"
#include "jsweakmap.h"
#include "jswrapper.h"
@ -573,6 +574,26 @@ intrinsic_ActiveFunction(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_SetCanonicalName(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
MOZ_ASSERT(fun->isSelfHostedBuiltin());
RootedAtom atom(cx, AtomizeString(cx, args[1].toString()));
if (!atom)
return false;
fun->setAtom(atom);
#ifdef DEBUG
fun->setExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT, BooleanValue(true));
#endif
args.rval().setUndefined();
return true;
}
static bool
intrinsic_StarGeneratorObjectIsClosed(JSContext* cx, unsigned argc, Value* vp)
{
@ -1546,6 +1567,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
CallNonGenericSelfhostedMethod<Is<ListIteratorObject>>, 2,0),
JS_FN("ActiveFunction", intrinsic_ActiveFunction, 0,0),
JS_FN("_SetCanonicalName", intrinsic_SetCanonicalName, 2,0),
JS_INLINABLE_FN("IsArrayIterator",
intrinsic_IsInstanceOfBuiltin<ArrayIteratorObject>, 1,0,
IntrinsicIsArrayIterator),
@ -2005,8 +2028,10 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject)
staticGlobalLexical, kind);
// To be able to re-lazify the cloned function, its name in the
// self-hosting compartment has to be stored on the clone.
if (clone && hasName)
clone->as<JSFunction>().setExtendedSlot(0, StringValue(selfHostedFunction->atom()));
if (clone && hasName) {
clone->as<JSFunction>().setExtendedSlot(LAZY_FUNCTION_NAME_SLOT,
StringValue(selfHostedFunction->atom()));
}
} else if (selfHostedObject->is<RegExpObject>()) {
RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
RootedAtom source(cx, reobj.getSource());
@ -2073,16 +2098,37 @@ CloneValue(JSContext* cx, HandleValue selfHostedValue, MutableHandleValue vp)
return true;
}
bool
JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName selfHostedName,
HandleAtom name, unsigned nargs,
MutableHandleFunction fun)
{
RootedAtom funName(cx, name);
JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, selfHostedName);
if (!selfHostedFun)
return false;
if (selfHostedFun->atom() != selfHostedName) {
MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
funName = selfHostedFun->atom();
}
fun.set(NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
funName, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject));
if (!fun)
return false;
fun->setIsSelfHostedBuiltin();
fun->setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, StringValue(selfHostedName));
return true;
}
bool
JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
HandleFunction targetFun)
{
RootedId id(cx, NameToId(name));
RootedValue funVal(cx);
if (!GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_), id, &funVal))
RootedFunction sourceFun(cx, getUnclonedSelfHostedFunction(cx, name));
if (!sourceFun)
return false;
RootedFunction sourceFun(cx, &funVal.toObject().as<JSFunction>());
// JSFunction::generatorKind can't handle lazy self-hosted functions, so we make sure there
// aren't any.
MOZ_ASSERT(!sourceFun->isGenerator());
@ -2112,11 +2158,28 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name,
}
bool
JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableHandleValue vp)
JSRuntime::getUnclonedSelfHostedValue(JSContext* cx, HandlePropertyName name,
MutableHandleValue vp)
{
RootedId id(cx, NameToId(name));
return GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_), id, vp);
}
JSFunction*
JSRuntime::getUnclonedSelfHostedFunction(JSContext* cx, HandlePropertyName name)
{
RootedValue selfHostedValue(cx);
if (!GetUnclonedValue(cx, HandleNativeObject::fromMarkedLocation(&selfHostingGlobal_), id, &selfHostedValue))
if (!getUnclonedSelfHostedValue(cx, name, &selfHostedValue))
return nullptr;
return &selfHostedValue.toObject().as<JSFunction>();
}
bool
JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableHandleValue vp)
{
RootedValue selfHostedValue(cx);
if (!getUnclonedSelfHostedValue(cx, name, &selfHostedValue))
return false;
/*
@ -2132,6 +2195,16 @@ JSRuntime::cloneSelfHostedValue(JSContext* cx, HandlePropertyName name, MutableH
return CloneValue(cx, selfHostedValue, vp);
}
void
JSRuntime::assertSelfHostedFunctionHasCanonicalName(JSContext* cx, HandlePropertyName name)
{
#ifdef DEBUG
JSFunction* selfHostedFun = getUnclonedSelfHostedFunction(cx, name);
MOZ_ASSERT(selfHostedFun);
MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean());
#endif
}
JSFunction*
js::SelfHostedFunction(JSContext* cx, HandlePropertyName propName)
{