Skip to content
Permalink
Browse files
Enable gigacage on iOS
https://bugs.webkit.org/show_bug.cgi?id=177586

Reviewed by JF Bastien.
JSTests:


Add tests for when Gigacage gets runtime disabled.

* stress/disable-gigacage-arrays.js: Added.
(foo):
* stress/disable-gigacage-strings.js: Added.
(foo):
* stress/disable-gigacage-typed-arrays.js: Added.
(foo):

Source/bmalloc:


Introduce the ability to disable gigacage at runtime if allocation fails. If any step of gigacage
allocation fails, we free all of the gigacages and turn off gigacage support.

Reland this after confirming that the 20% Kraken regression was a one-bot fluke. Local testing on the
same kind of system did not show the regression. Saam and I both tried independently.

* CMakeLists.txt:
* bmalloc.xcodeproj/project.pbxproj:
* bmalloc/Cache.cpp:
(bmalloc::Cache::scavenge):
* bmalloc/Cache.h:
(bmalloc::Cache::tryAllocate):
(bmalloc::Cache::allocate):
(bmalloc::Cache::deallocate):
(bmalloc::Cache::reallocate):
* bmalloc/Gigacage.cpp:
(Gigacage::ensureGigacage):
(Gigacage::runway):
(Gigacage::totalSize):
(Gigacage::shouldBeEnabled):
(): Deleted.
(Gigacage::Callback::Callback): Deleted.
(Gigacage::Callback::function): Deleted.
(Gigacage::PrimitiveDisableCallbacks::PrimitiveDisableCallbacks): Deleted.
* bmalloc/Gigacage.h:
(Gigacage::wasEnabled):
(Gigacage::isEnabled):
(Gigacage::runway): Deleted.
(Gigacage::totalSize): Deleted.
* bmalloc/HeapKind.cpp: Added.
(bmalloc::isActiveHeapKind):
(bmalloc::mapToActiveHeapKind):
* bmalloc/HeapKind.h:
(bmalloc::isActiveHeapKindAfterEnsuringGigacage):
(bmalloc::mapToActiveHeapKindAfterEnsuringGigacage):
* bmalloc/Scavenger.cpp:
(bmalloc::Scavenger::scavenge):
* bmalloc/bmalloc.h:
(bmalloc::api::tryLargeMemalignVirtual):
(bmalloc::api::freeLargeVirtual):
(bmalloc::api::isEnabled):

Source/JavaScriptCore:


The hardest part of enabling Gigacage on iOS is that it requires loading global variables while
executing JS, so the LLInt needs to know how to load from global variables on all platforms that
have Gigacage. So, this teaches ARM64 how to load from global variables.

Also, this makes the code handle disabling the gigacage a bit better.

* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::caged):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::cage):
(JSC::AssemblyHelpers::cageConditionally):
* offlineasm/arm64.rb:
* offlineasm/asm.rb:
* offlineasm/instructions.rb:

Tools:


Add a mode to test disabling Gigacage.

* Scripts/run-jsc-stress-tests:
* Scripts/webkitruby/jsc-stress-test-writer-default.rb:



Canonical link: https://commits.webkit.org/194358@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
pizlonator committed Oct 10, 2017
1 parent c566678 commit e73b10d9ada24ff68b5bbd18c7fd9ebc0e17cca9
Showing 25 changed files with 460 additions and 52 deletions.
@@ -1,3 +1,19 @@
2017-09-29 Filip Pizlo <fpizlo@apple.com>

Enable gigacage on iOS
https://bugs.webkit.org/show_bug.cgi?id=177586

Reviewed by JF Bastien.

Add tests for when Gigacage gets runtime disabled.

* stress/disable-gigacage-arrays.js: Added.
(foo):
* stress/disable-gigacage-strings.js: Added.
(foo):
* stress/disable-gigacage-typed-arrays.js: Added.
(foo):

2017-10-09 Michael Saboff <msaboff@apple.com>

Implement RegExp Unicode property escapes
@@ -0,0 +1,24 @@
//@ runNoisyTestWithEnv "disable-gigacage", "GIGACAGE_ENABLED=0"

(function() {
function foo(array, i)
{
return array[i];
}

noInline(foo);

var array = new Array(1000);
for (var i = 0; i < array.length; ++i)
array[i] = 5 - i;
for (var i = 0; i < 1000; ++i) {
var result = 0;
var expectedResult = 0;
for (var j = 0; j < array.length; ++j) {
result += foo(array, j);
expectedResult += 5 - j;
}
if (result != expectedResult)
throw new Error("Bad result: " + result);
}
})();
@@ -0,0 +1,25 @@
//@ runNoisyTestWithEnv "disable-gigacage", "GIGACAGE_ENABLED=0"

(function() {
function foo(array, i)
{
return array.charCodeAt(i);
}

noInline(foo);

var array = "";
for (var i = 0; i < array.length; ++i)
array += String.fromCharCode(5 - i);
for (var i = 0; i < 1000; ++i) {
var result = 0;
var expectedResult = 0;
for (var j = 0; j < array.length; ++j) {
result += foo(array, j);
expectedResult += 5 - j;
}
if (result != expectedResult)
throw new Error("Bad result: " + result);
}
})();

@@ -0,0 +1,25 @@
//@ runNoisyTestWithEnv "disable-gigacage", "GIGACAGE_ENABLED=0"

(function() {
function foo(array, i)
{
return array[i];
}

noInline(foo);

var array = new Int32Array(1000);
for (var i = 0; i < array.length; ++i)
array[i] = 5 - i;
for (var i = 0; i < 1000; ++i) {
var result = 0;
var expectedResult = 0;
for (var j = 0; j < array.length; ++j) {
result += foo(array, j);
expectedResult += 5 - j;
}
if (result != expectedResult)
throw new Error("Bad result: " + result);
}
})();

@@ -1,3 +1,25 @@
2017-09-29 Filip Pizlo <fpizlo@apple.com>

Enable gigacage on iOS
https://bugs.webkit.org/show_bug.cgi?id=177586

Reviewed by JF Bastien.

The hardest part of enabling Gigacage on iOS is that it requires loading global variables while
executing JS, so the LLInt needs to know how to load from global variables on all platforms that
have Gigacage. So, this teaches ARM64 how to load from global variables.

Also, this makes the code handle disabling the gigacage a bit better.

* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::caged):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::cage):
(JSC::AssemblyHelpers::cageConditionally):
* offlineasm/arm64.rb:
* offlineasm/asm.rb:
* offlineasm/instructions.rb:

2017-10-09 Robin Morisset <rmorisset@apple.com>

Evaluate the benefit of skipping dead code in the DFGByteCodeParser when a function returns in its first block
@@ -11994,7 +11994,7 @@ class LowerDFGToB3 {

LValue caged(Gigacage::Kind kind, LValue ptr)
{
if (!Gigacage::shouldBeEnabled())
if (!Gigacage::isEnabled(kind))
return ptr;

if (kind == Gigacage::Primitive && Gigacage::canPrimitiveGigacageBeDisabled()) {
@@ -1314,7 +1314,7 @@ class AssemblyHelpers : public MacroAssembler {
void cage(Gigacage::Kind kind, GPRReg storage)
{
#if GIGACAGE_ENABLED
if (!Gigacage::shouldBeEnabled())
if (!Gigacage::isEnabled(kind))
return;

andPtr(TrustedImmPtr(Gigacage::mask(kind)), storage);
@@ -1328,7 +1328,7 @@ class AssemblyHelpers : public MacroAssembler {
void cageConditionally(Gigacage::Kind kind, GPRReg storage, GPRReg scratch)
{
#if GIGACAGE_ENABLED
if (!Gigacage::shouldBeEnabled())
if (!Gigacage::isEnabled(kind))
return;

if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacageDisabled())
@@ -260,6 +260,31 @@ def isAddressMalformed(operand)
newList
end

def arm64LowerLabelReferences(list)
newList = []
list.each {
| node |
if node.is_a? Instruction
case node.opcode
when "loadi", "loadis", "loadp", "loadq", "loadb", "loadbs", "loadh", "loadhs"
labelRef = node.operands[0]
if labelRef.is_a? LabelReference
tmp = Tmp.new(node.codeOrigin, :gpr)
newList << Instruction.new(codeOrigin, "globaladdr", [LabelReference.new(node.codeOrigin, labelRef.label), tmp])
newList << Instruction.new(codeOrigin, node.opcode, [Address.new(node.codeOrigin, tmp, Immediate.new(node.codeOrigin, labelRef.offset)), node.operands[1]])
else
newList << node
end
else
newList << node
end
else
newList << node
end
}
newList
end

# Workaround for Cortex-A53 erratum (835769)
def arm64CortexA53Fix835769(list)
newList = []
@@ -296,6 +321,7 @@ def getModifiedListARM64
result = riscLowerHardBranchOps64(result)
result = riscLowerShiftOps(result)
result = arm64LowerMalformedLoadStoreAddresses(result)
result = arm64LowerLabelReferences(result)
result = riscLowerMalformedAddresses(result) {
| node, address |
case node.opcode
@@ -904,6 +930,15 @@ def lowerARM64
$asm.putStr("#if CPU(ARM64_CORTEXA53)")
$asm.puts "nop"
$asm.putStr("#endif")
when "globaladdr"
uid = $asm.newUID
$asm.puts "L_offlineasm_loh_adrp_#{uid}:"
$asm.puts "adrp #{operands[1].arm64Operand(:ptr)}, #{operands[0].asmLabel}@GOTPAGE"
$asm.puts "L_offlineasm_loh_ldr_#{uid}:"
$asm.puts "ldr #{operands[1].arm64Operand(:ptr)}, [#{operands[1].arm64Operand(:ptr)}, #{operands[0].asmLabel}@GOTPAGEOFF]"
$asm.deferAction {
$asm.puts ".loh AdrpLdrGot L_offlineasm_loh_adrp_#{uid}, L_offlineasm_loh_ldr_#{uid}"
}
else
lowerDefault
end
@@ -46,6 +46,8 @@ def initialize(outp)
@codeOrigin = nil
@numLocalLabels = 0
@numGlobalLabels = 0
@deferredActions = []
@count = 0

@newlineSpacerState = :none
@lastlabel = ""
@@ -73,10 +75,23 @@ def leaveAsm
putsProcEndIfNeeded
end
putsLastComment
@deferredActions.each {
| action |
action.call()
}
@outp.puts "OFFLINE_ASM_END" if !$emitWinAsm
@state = :cpp
end

def deferAction(&proc)
@deferredActions << proc
end

def newUID
@count += 1
@count
end

def inAsm
enterAsm
yield
@@ -267,7 +267,8 @@
ARM64_INSTRUCTIONS =
[
"pcrtoaddr", # Address from PC relative offset - adr instruction
"nopFixCortexA53Err835769" # nop on Cortex-A53 (nothing otherwise)
"nopFixCortexA53Err835769", # nop on Cortex-A53 (nothing otherwise)
"globaladdr"
]

RISC_INSTRUCTIONS =
@@ -13,6 +13,7 @@ set(bmalloc_SOURCES
bmalloc/Environment.cpp
bmalloc/Gigacage.cpp
bmalloc/Heap.cpp
bmalloc/HeapKind.cpp
bmalloc/LargeMap.cpp
bmalloc/Logging.cpp
bmalloc/ObjectType.cpp
@@ -1,3 +1,52 @@
2017-09-29 Filip Pizlo <fpizlo@apple.com>

Enable gigacage on iOS
https://bugs.webkit.org/show_bug.cgi?id=177586

Reviewed by JF Bastien.

Introduce the ability to disable gigacage at runtime if allocation fails. If any step of gigacage
allocation fails, we free all of the gigacages and turn off gigacage support.

Reland this after confirming that the 20% Kraken regression was a one-bot fluke. Local testing on the
same kind of system did not show the regression. Saam and I both tried independently.

* CMakeLists.txt:
* bmalloc.xcodeproj/project.pbxproj:
* bmalloc/Cache.cpp:
(bmalloc::Cache::scavenge):
* bmalloc/Cache.h:
(bmalloc::Cache::tryAllocate):
(bmalloc::Cache::allocate):
(bmalloc::Cache::deallocate):
(bmalloc::Cache::reallocate):
* bmalloc/Gigacage.cpp:
(Gigacage::ensureGigacage):
(Gigacage::runway):
(Gigacage::totalSize):
(Gigacage::shouldBeEnabled):
(): Deleted.
(Gigacage::Callback::Callback): Deleted.
(Gigacage::Callback::function): Deleted.
(Gigacage::PrimitiveDisableCallbacks::PrimitiveDisableCallbacks): Deleted.
* bmalloc/Gigacage.h:
(Gigacage::wasEnabled):
(Gigacage::isEnabled):
(Gigacage::runway): Deleted.
(Gigacage::totalSize): Deleted.
* bmalloc/HeapKind.cpp: Added.
(bmalloc::isActiveHeapKind):
(bmalloc::mapToActiveHeapKind):
* bmalloc/HeapKind.h:
(bmalloc::isActiveHeapKindAfterEnsuringGigacage):
(bmalloc::mapToActiveHeapKindAfterEnsuringGigacage):
* bmalloc/Scavenger.cpp:
(bmalloc::Scavenger::scavenge):
* bmalloc/bmalloc.h:
(bmalloc::api::tryLargeMemalignVirtual):
(bmalloc::api::freeLargeVirtual):
(bmalloc::api::isEnabled):

2017-10-09 Commit Queue <commit-queue@webkit.org>

Unreviewed, rolling out r223015 and r223025.
@@ -15,6 +15,7 @@
0F5BF1521F22E1570029D91D /* Scavenger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5BF1501F22E1570029D91D /* Scavenger.cpp */; };
0F5BF1531F22E1570029D91D /* Scavenger.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5BF1511F22E1570029D91D /* Scavenger.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F5BF1731F23C5710029D91D /* BExport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5BF1721F23C5710029D91D /* BExport.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FD557331F7EDB7B00B1F0A3 /* HeapKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD557321F7EDB7B00B1F0A3 /* HeapKind.cpp */; };
1400274918F89C1300115C97 /* Heap.h in Headers */ = {isa = PBXBuildFile; fileRef = 14DA320C18875B09007269E0 /* Heap.h */; settings = {ATTRIBUTES = (Private, ); }; };
1400274A18F89C2300115C97 /* VMHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = 144F7BFC18BFC517003537F3 /* VMHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
140FA00319CE429C00FFD3C8 /* BumpRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 140FA00219CE429C00FFD3C8 /* BumpRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -90,6 +91,7 @@
0F5BF1501F22E1570029D91D /* Scavenger.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Scavenger.cpp; path = bmalloc/Scavenger.cpp; sourceTree = "<group>"; };
0F5BF1511F22E1570029D91D /* Scavenger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Scavenger.h; path = bmalloc/Scavenger.h; sourceTree = "<group>"; };
0F5BF1721F23C5710029D91D /* BExport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BExport.h; path = bmalloc/BExport.h; sourceTree = "<group>"; };
0FD557321F7EDB7B00B1F0A3 /* HeapKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HeapKind.cpp; path = bmalloc/HeapKind.cpp; sourceTree = "<group>"; };
140FA00219CE429C00FFD3C8 /* BumpRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BumpRange.h; path = bmalloc/BumpRange.h; sourceTree = "<group>"; };
140FA00419CE4B6800FFD3C8 /* LineMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineMetadata.h; path = bmalloc/LineMetadata.h; sourceTree = "<group>"; };
14105E8318E14374003A106E /* ObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectType.cpp; path = bmalloc/ObjectType.cpp; sourceTree = "<group>"; };
@@ -287,6 +289,7 @@
1413E460189DCE1E00546D68 /* BInline.h */,
14C919C818FCC59F0028DB43 /* BPlatform.h */,
14D9DB4517F2447100EAAB79 /* FixedVector.h */,
0FD557321F7EDB7B00B1F0A3 /* HeapKind.cpp */,
0F5BF1461F22A8B10029D91D /* HeapKind.h */,
141D9AFF1C8E51C0000ABBA0 /* List.h */,
4426E27E1C838EE0008EB042 /* Logging.cpp */,
@@ -456,6 +459,7 @@
buildActionMask = 2147483647;
files = (
0F5BF1521F22E1570029D91D /* Scavenger.cpp in Sources */,
0FD557331F7EDB7B00B1F0A3 /* HeapKind.cpp in Sources */,
14F271C318EA3978008C152F /* Allocator.cpp in Sources */,
6599C5CC1EC3F15900A2F7BB /* AvailableMemory.cpp in Sources */,
14F271C418EA397B008C152F /* Cache.cpp in Sources */,
@@ -35,6 +35,8 @@ void Cache::scavenge(HeapKind heapKind)
PerHeapKind<Cache>* caches = PerThread<PerHeapKind<Cache>>::getFastCase();
if (!caches)
return;
if (!isActiveHeapKind(heapKind))
return;

caches->at(heapKind).allocator().scavenge();
caches->at(heapKind).deallocator().scavenge();
@@ -48,27 +50,27 @@ Cache::Cache(HeapKind heapKind)

BNO_INLINE void* Cache::tryAllocateSlowCaseNullCache(HeapKind heapKind, size_t size)
{
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(heapKind).allocator().tryAllocate(size);
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(mapToActiveHeapKind(heapKind)).allocator().tryAllocate(size);
}

BNO_INLINE void* Cache::allocateSlowCaseNullCache(HeapKind heapKind, size_t size)
{
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(heapKind).allocator().allocate(size);
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(mapToActiveHeapKind(heapKind)).allocator().allocate(size);
}

BNO_INLINE void* Cache::allocateSlowCaseNullCache(HeapKind heapKind, size_t alignment, size_t size)
{
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(heapKind).allocator().allocate(alignment, size);
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(mapToActiveHeapKind(heapKind)).allocator().allocate(alignment, size);
}

BNO_INLINE void Cache::deallocateSlowCaseNullCache(HeapKind heapKind, void* object)
{
PerThread<PerHeapKind<Cache>>::getSlowCase()->at(heapKind).deallocator().deallocate(object);
PerThread<PerHeapKind<Cache>>::getSlowCase()->at(mapToActiveHeapKind(heapKind)).deallocator().deallocate(object);
}

BNO_INLINE void* Cache::reallocateSlowCaseNullCache(HeapKind heapKind, void* object, size_t newSize)
{
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(heapKind).allocator().reallocate(object, newSize);
return PerThread<PerHeapKind<Cache>>::getSlowCase()->at(mapToActiveHeapKind(heapKind)).allocator().reallocate(object, newSize);
}

} // namespace bmalloc

0 comments on commit e73b10d

Please sign in to comment.