Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (231888 => 231889)
--- trunk/Source/_javascript_Core/ChangeLog 2018-05-17 05:21:22 UTC (rev 231888)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-05-17 05:21:41 UTC (rev 231889)
@@ -1,5 +1,35 @@
2018-05-16 Saam Barati <sbar...@apple.com>
+ UnlinkedFunctionExecutable doesn't need a parent source override field since it's only used for default class constructors
+ https://bugs.webkit.org/show_bug.cgi?id=185637
+
+ Reviewed by Keith Miller.
+
+ We had this general mechanism for overriding an UnlinkedFunctionExecutable's parent
+ source code. However, we were only using this for default class constructors. There
+ are only two types of default class constructors. This patch makes it so that
+ we just store this information inside of a single bit, and ask for the source
+ code as needed instead of holding it in a nullable field that is 24 bytes in size.
+
+ This brings UnlinkedFunctionExecutable's size down from 184 bytes to 160 bytes.
+ This has the consequence of making it allocated out of a 160 byte size class
+ instead of a 224 byte size class. This should bring down its memory footprint
+ by ~40%.
+
+ * builtins/BuiltinExecutables.cpp:
+ (JSC::BuiltinExecutables::defaultConstructorSourceCode):
+ (JSC::BuiltinExecutables::createDefaultConstructor):
+ (JSC::BuiltinExecutables::createExecutable):
+ * builtins/BuiltinExecutables.h:
+ * bytecode/UnlinkedFunctionExecutable.cpp:
+ (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+ (JSC::UnlinkedFunctionExecutable::link):
+ * bytecode/UnlinkedFunctionExecutable.h:
+ * runtime/CodeCache.cpp:
+ (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
+
+2018-05-16 Saam Barati <sbar...@apple.com>
+
VM::shrinkFootprint should call collectNow(Sync) instead of collectSync so it also eagerly sweeps
https://bugs.webkit.org/show_bug.cgi?id=185707
Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp (231888 => 231889)
--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp 2018-05-17 05:21:22 UTC (rev 231888)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp 2018-05-17 05:21:41 UTC (rev 231889)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -42,18 +42,41 @@
{
}
+const SourceCode& BuiltinExecutables::defaultConstructorSourceCode(ConstructorKind constructorKind)
+{
+ switch (constructorKind) {
+ case ConstructorKind::None:
+ RELEASE_ASSERT_NOT_REACHED();
+ case ConstructorKind::Base: {
+ static NeverDestroyed<const String> baseConstructorCode(MAKE_STATIC_STRING_IMPL("(function () { })"));
+ static LazyNeverDestroyed<SourceCode> result;
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [&] {
+ result.construct(makeSource(baseConstructorCode, { }));
+ });
+ return result;
+ }
+ case ConstructorKind::Extends: {
+ static NeverDestroyed<const String> derivedConstructorCode(MAKE_STATIC_STRING_IMPL("(function (...args) { super(...args); })"));
+ static LazyNeverDestroyed<SourceCode> result;
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [&] {
+ result.construct(makeSource(derivedConstructorCode, { }));
+ });
+ return result;
+ }
+ }
+}
+
UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name)
{
- static NeverDestroyed<const String> baseConstructorCode(MAKE_STATIC_STRING_IMPL("(function () { })"));
- static NeverDestroyed<const String> derivedConstructorCode(MAKE_STATIC_STRING_IMPL("(function (...args) { super(...args); })"));
switch (constructorKind) {
case ConstructorKind::None:
break;
case ConstructorKind::Base:
- return createExecutable(m_vm, makeSource(baseConstructorCode, { }), name, constructorKind, ConstructAbility::CanConstruct);
case ConstructorKind::Extends:
- return createExecutable(m_vm, makeSource(derivedConstructorCode, { }), name, constructorKind, ConstructAbility::CanConstruct);
+ return createExecutable(m_vm, defaultConstructorSourceCode(constructorKind), name, constructorKind, ConstructAbility::CanConstruct);
}
ASSERT_NOT_REACHED();
return nullptr;
@@ -73,10 +96,9 @@
{
JSTextPosition positionBeforeLastNewline;
ParserError error;
- bool isParsingDefaultConstructor = constructorKind != ConstructorKind::None;
- JSParserBuiltinMode builtinMode = isParsingDefaultConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin;
- UnlinkedFunctionKind kind = isParsingDefaultConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction;
- SourceCode parentSourceOverride = isParsingDefaultConstructor ? source : SourceCode();
+ bool isBuiltinDefaultClassConstructor = constructorKind != ConstructorKind::None;
+ JSParserBuiltinMode builtinMode = isBuiltinDefaultClassConstructor ? JSParserBuiltinMode::NotBuiltin : JSParserBuiltinMode::Builtin;
+ UnlinkedFunctionKind kind = isBuiltinDefaultClassConstructor ? UnlinkedNormalFunction : UnlinkedBuiltinFunction;
std::unique_ptr<ProgramNode> program = parse<ProgramNode>(
&vm, source, Identifier(), builtinMode,
JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error,
@@ -105,7 +127,7 @@
RELEASE_ASSERT(metadata);
metadata->overrideName(name);
VariableEnvironment dummyTDZVariables;
- UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, WTFMove(parentSourceOverride));
+ UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, isBuiltinDefaultClassConstructor);
return functionExecutable;
}
Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.h (231888 => 231889)
--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.h 2018-05-17 05:21:22 UTC (rev 231888)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.h 2018-05-17 05:21:41 UTC (rev 231889)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -49,6 +49,7 @@
JSC_FOREACH_BUILTIN_CODE(EXPOSE_BUILTIN_EXECUTABLES)
#undef EXPOSE_BUILTIN_SOURCES
+ static const SourceCode& defaultConstructorSourceCode(ConstructorKind);
UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name);
static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility);
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (231888 => 231889)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2018-05-17 05:21:22 UTC (rev 231888)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp 2018-05-17 05:21:41 UTC (rev 231889)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013, 2015-2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,6 +26,7 @@
#include "config.h"
#include "UnlinkedFunctionExecutable.h"
+#include "BuiltinExecutables.h"
#include "BytecodeGenerator.h"
#include "ClassInfo.h"
#include "CodeCache.h"
@@ -40,7 +41,7 @@
namespace JSC {
-static_assert(sizeof(UnlinkedFunctionExecutable) <= 256, "UnlinkedFunctionExecutable should fit in a 256-byte cell.");
+static_assert(sizeof(UnlinkedFunctionExecutable) <= 160, "UnlinkedFunctionExecutable should fit in a 160-byte cell. If you increase the size of this class, consider making a size class that perfectly fits it.");
const ClassInfo UnlinkedFunctionExecutable::s_info = { "UnlinkedFunctionExecutable", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(UnlinkedFunctionExecutable) };
@@ -76,7 +77,7 @@
return result;
}
-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& parentSource, SourceCode&& parentSourceOverride, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType)
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor)
: Base(*vm, structure)
, m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt())
, m_lineCount(node->lastLine() - node->firstLine())
@@ -94,6 +95,7 @@
, m_isInStrictContext(node->isInStrictContext())
, m_hasCapturedVariables(false)
, m_isBuiltinFunction(kind == UnlinkedBuiltinFunction)
+ , m_isBuiltinDefaultClassConstructor(isBuiltinDefaultClassConstructor)
, m_constructAbility(static_cast<unsigned>(constructAbility))
, m_constructorKind(static_cast<unsigned>(node->constructorKind()))
, m_functionMode(static_cast<unsigned>(node->functionMode()))
@@ -103,7 +105,6 @@
, m_name(node->ident())
, m_ecmaName(node->ecmaName())
, m_inferredName(node->inferredName())
- , m_parentSourceOverride(WTFMove(parentSourceOverride))
, m_classSource(node->classSource())
, m_parentScopeTDZVariables(vm->m_compactVariableMap->get(parentScopeTDZVariables))
{
@@ -114,6 +115,7 @@
ASSERT(m_scriptMode == static_cast<unsigned>(scriptMode));
ASSERT(m_superBinding == static_cast<unsigned>(node->superBinding()));
ASSERT(m_derivedContextType == static_cast<unsigned>(derivedContextType));
+ ASSERT(!(m_isBuiltinDefaultClassConstructor && constructorKind() == ConstructorKind::None));
}
void UnlinkedFunctionExecutable::destroy(JSCell* cell)
@@ -132,7 +134,7 @@
FunctionExecutable* UnlinkedFunctionExecutable::link(VM& vm, const SourceCode& passedParentSource, std::optional<int> overrideLineNumber, Intrinsic intrinsic)
{
- const SourceCode& parentSource = m_parentSourceOverride.isNull() ? passedParentSource : m_parentSourceOverride;
+ const SourceCode& parentSource = !m_isBuiltinDefaultClassConstructor ? passedParentSource : BuiltinExecutables::defaultConstructorSourceCode(constructorKind());
unsigned firstLine = parentSource.firstLine().oneBasedInt() + m_firstLineOffset;
unsigned startOffset = parentSource.startOffset() + m_startOffset;
unsigned lineCount = m_lineCount;
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (231888 => 231889)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2018-05-17 05:21:22 UTC (rev 231888)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h 2018-05-17 05:21:41 UTC (rev 231889)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012-2018 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -58,10 +58,10 @@
typedef JSCell Base;
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
- static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, SourceCode&& parentSourceOverride = SourceCode())
+ static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment& parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false)
{
UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap))
- UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, WTFMove(parentSourceOverride), node, unlinkedFunctionKind, constructAbility, scriptMode, parentScopeTDZVariables, derivedContextType);
+ UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, parentScopeTDZVariables, derivedContextType, isBuiltinDefaultClassConstructor);
instance->finishCreation(*vm);
return instance;
}
@@ -139,7 +139,7 @@
void setSourceMappingURLDirective(const String& sourceMappingURL) { m_sourceMappingURLDirective = sourceMappingURL; }
private:
- UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, SourceCode&& parentSourceOverride, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, VariableEnvironment&, JSC::DerivedContextType);
+ UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, VariableEnvironment&, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);
unsigned m_firstLineOffset;
unsigned m_lineCount;
@@ -157,6 +157,7 @@
unsigned m_isInStrictContext : 1;
unsigned m_hasCapturedVariables : 1;
unsigned m_isBuiltinFunction : 1;
+ unsigned m_isBuiltinDefaultClassConstructor : 1;
unsigned m_constructAbility: 1;
unsigned m_constructorKind : 2;
unsigned m_functionMode : 2; // FunctionMode
@@ -170,7 +171,6 @@
Identifier m_name;
Identifier m_ecmaName;
Identifier m_inferredName;
- SourceCode m_parentSourceOverride;
SourceCode m_classSource;
String m_sourceURLDirective;
Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (231888 => 231889)
--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp 2018-05-17 05:21:22 UTC (rev 231888)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp 2018-05-17 05:21:41 UTC (rev 231889)
@@ -150,7 +150,8 @@
metadata->overrideName(name);
metadata->setEndPosition(positionBeforeLastNewline);
- // The Function constructor only has access to global variables, so no variables will be under TDZ.
+ // The Function constructor only has access to global variables, so no variables will be under TDZ unless they're
+ // in the global lexical environment, which we always TDZ check accesses from.
VariableEnvironment emptyTDZVariables;
ConstructAbility constructAbility = constructAbilityForParseMode(metadata->parseMode());
UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, emptyTDZVariables, DerivedContextType::None);