Diff
Modified: trunk/JSTests/ChangeLog (229841 => 229842)
--- trunk/JSTests/ChangeLog 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/JSTests/ChangeLog 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1,3 +1,15 @@
+2018-03-21 Filip Pizlo <[email protected]>
+
+ ScopedArguments should do poisoning and index masking
+ https://bugs.webkit.org/show_bug.cgi?id=183863
+
+ Reviewed by Mark Lam.
+
+ Adds another stress test of scoped arguments.
+
+ * stress/scoped-arguments-test.js: Added.
+ (foo):
+
2018-03-20 Saam Barati <[email protected]>
We need to do proper bookkeeping of exitOK when inserting constants when sinking NewArrayBuffer
Added: trunk/JSTests/stress/scoped-arguments-test.js (0 => 229842)
--- trunk/JSTests/stress/scoped-arguments-test.js (rev 0)
+++ trunk/JSTests/stress/scoped-arguments-test.js 2018-03-22 02:15:44 UTC (rev 229842)
@@ -0,0 +1,16 @@
+function foo(a)
+{
+ (function() { return a; })();
+ return [arguments[0], arguments];
+}
+
+noInline(foo);
+
+for (var i = 0; i < 10000; ++i) {
+ var result = foo(42);
+ if (result[0] != 42)
+ throw new Error("result[0] is not 42: " + result[0]);
+ if (result[1][0] != 42)
+ throw new Error("result[1][0] is not 42: " + result[1][0]);
+}
+
Modified: trunk/Source/_javascript_Core/ChangeLog (229841 => 229842)
--- trunk/Source/_javascript_Core/ChangeLog 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1,3 +1,30 @@
+2018-03-21 Filip Pizlo <[email protected]>
+
+ ScopedArguments should do poisoning and index masking
+ https://bugs.webkit.org/show_bug.cgi?id=183863
+
+ Reviewed by Mark Lam.
+
+ This outlines the ScopedArguments overflow storage and adds poisoning.
+
+ * bytecode/AccessCase.cpp:
+ (JSC::AccessCase::generateWithGuard):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileGetByValOnScopedArguments):
+ (JSC::DFG::SpeculativeJIT::compileGetArrayLength):
+ * ftl/FTLAbstractHeapRepository.h:
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emitScopedArgumentsGetByVal):
+ * runtime/JSCPoison.h:
+ * runtime/ScopedArguments.cpp:
+ (JSC::ScopedArguments::ScopedArguments):
+ (JSC::ScopedArguments::createUninitialized):
+ (JSC::ScopedArguments::visitChildren):
+ * runtime/ScopedArguments.h:
+
2018-03-21 Mark Lam <[email protected]>
Refactor the PtrTag list as a macro so that we can auto-generate code that enumerates each PtrTag.
Modified: trunk/Source/_javascript_Core/bytecode/AccessCase.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/bytecode/AccessCase.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/bytecode/AccessCase.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -403,12 +403,16 @@
CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()),
CCallHelpers::TrustedImm32(ScopedArgumentsType)));
+ jit.loadPtr(
+ CCallHelpers::Address(baseGPR, ScopedArguments::offsetOfStorage()),
+ scratchGPR);
+ jit.xorPtr(CCallHelpers::TrustedImmPtr(ScopedArgumentsPoison::key()), scratchGPR);
fallThrough.append(
jit.branchTest8(
CCallHelpers::NonZero,
- CCallHelpers::Address(baseGPR, ScopedArguments::offsetOfOverrodeThings())));
+ CCallHelpers::Address(scratchGPR, ScopedArguments::offsetOfOverrodeThingsInStorage())));
jit.load32(
- CCallHelpers::Address(baseGPR, ScopedArguments::offsetOfTotalLength()),
+ CCallHelpers::Address(scratchGPR, ScopedArguments::offsetOfTotalLengthInStorage()),
valueRegs.payloadGPR());
jit.boxInt32(valueRegs.payloadGPR(), valueRegs);
state.succeed();
Modified: trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/dfg/DFGArrayMode.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2017 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
@@ -271,6 +271,8 @@
return ArrayMode(type, Array::NonArray, Array::OutOfBounds, Array::AsIs);
return ArrayMode(Array::Generic);
}
+ if (isX86() && is32Bit() && isScopedArgumentsSpeculation(base))
+ return ArrayMode(Array::Generic);
return withType(type);
}
Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -217,7 +217,7 @@
DirectArguments* result = DirectArguments::create(
vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
- result->callee().set(vm, result, callee);
+ result->setCallee(vm, callee);
void* frameBase = context.fp<Register*>() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0);
Frame frame(frameBase, context.stack());
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1701,7 +1701,7 @@
DirectArguments* result = DirectArguments::create(
vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
- result->callee().set(vm, result, callee);
+ result->setCallee(vm, callee);
Register* arguments =
exec->registers() + (inlineCallFrame ? inlineCallFrame->stackOffset : 0) +
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -6488,6 +6488,7 @@
#endif
GPRTemporary scratch(this);
GPRTemporary scratch2(this);
+ GPRTemporary indexMask(this);
GPRReg baseReg = base.gpr();
GPRReg propertyReg = property.gpr();
@@ -6500,6 +6501,7 @@
#endif
GPRReg scratchReg = scratch.gpr();
GPRReg scratch2Reg = scratch2.gpr();
+ GPRReg indexMaskReg = indexMask.gpr();
if (!m_compileOkay)
return;
@@ -6506,13 +6508,22 @@
ASSERT(ArrayMode(Array::ScopedArguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(m_graph.varArgChild(node, 0))));
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, ScopedArguments::offsetOfStorage()), resultReg);
+ m_jit.xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), resultReg);
+
+ m_jit.load32(
+ MacroAssembler::Address(resultReg, ScopedArguments::offsetOfTotalLengthInStorage()),
+ scratchReg);
+
speculationCheck(
ExoticObjectMode, JSValueSource(), nullptr,
- m_jit.branch32(
- MacroAssembler::AboveOrEqual, propertyReg,
- MacroAssembler::Address(baseReg, ScopedArguments::offsetOfTotalLength())));
+ m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, scratchReg));
+ m_jit.emitPreparePreciseIndexMask32(propertyReg, scratchReg, indexMaskReg);
+
m_jit.loadPtr(MacroAssembler::Address(baseReg, ScopedArguments::offsetOfTable()), scratchReg);
+ m_jit.xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), scratchReg);
m_jit.load32(
MacroAssembler::Address(scratchReg, ScopedArgumentsTable::offsetOfLength()), scratch2Reg);
@@ -6520,6 +6531,7 @@
MacroAssembler::AboveOrEqual, propertyReg, scratch2Reg);
m_jit.loadPtr(MacroAssembler::Address(baseReg, ScopedArguments::offsetOfScope()), scratch2Reg);
+ m_jit.xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), scratch2Reg);
m_jit.loadPtr(
MacroAssembler::Address(scratchReg, ScopedArgumentsTable::offsetOfArguments()),
@@ -6547,13 +6559,14 @@
m_jit.loadValue(
MacroAssembler::BaseIndex(
- baseReg, scratch2Reg, MacroAssembler::TimesEight,
- ScopedArguments::overflowStorageOffset()),
+ resultReg, scratch2Reg, MacroAssembler::TimesEight),
resultRegs);
speculationCheck(ExoticObjectMode, JSValueSource(), nullptr, m_jit.branchIfEmpty(resultRegs));
done.link(&m_jit);
+ m_jit.andPtr(indexMaskReg, resultReg);
+
jsValueResult(resultRegs, node);
}
@@ -6650,8 +6663,7 @@
m_jit.loadPtr(
MacroAssembler::Address(baseReg, DirectArguments::offsetOfStorage()), resultReg);
- m_jit.xorPtr(
- TrustedImmPtr(DirectArgumentsPoison::key()), resultReg);
+ m_jit.xorPtr(TrustedImmPtr(DirectArgumentsPoison::key()), resultReg);
m_jit.load32(
MacroAssembler::Address(resultReg, DirectArguments::offsetOfLengthInStorage()), resultReg);
@@ -6660,7 +6672,7 @@
}
case Array::ScopedArguments: {
SpeculateCellOperand base(this, node->child1());
- GPRTemporary result(this, Reuse, base);
+ GPRTemporary result(this);
GPRReg baseReg = base.gpr();
GPRReg resultReg = result.gpr();
@@ -6670,14 +6682,18 @@
ASSERT(ArrayMode(Array::ScopedArguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
+ m_jit.loadPtr(
+ MacroAssembler::Address(baseReg, ScopedArguments::offsetOfStorage()), resultReg);
+ m_jit.xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), resultReg);
+
speculationCheck(
ExoticObjectMode, JSValueSource(), 0,
m_jit.branchTest8(
MacroAssembler::NonZero,
- MacroAssembler::Address(baseReg, ScopedArguments::offsetOfOverrodeThings())));
+ MacroAssembler::Address(resultReg, ScopedArguments::offsetOfOverrodeThingsInStorage())));
m_jit.load32(
- MacroAssembler::Address(baseReg, ScopedArguments::offsetOfTotalLength()), resultReg);
+ MacroAssembler::Address(resultReg, ScopedArguments::offsetOfTotalLengthInStorage()), resultReg);
int32Result(resultReg, node);
break;
Modified: trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h (229841 => 229842)
--- trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/ftl/FTLAbstractHeapRepository.h 2018-03-22 02:15:44 UTC (rev 229842)
@@ -102,10 +102,11 @@
macro(ShadowChicken_Packet_scope, OBJECT_OFFSETOF(ShadowChicken::Packet, scope)) \
macro(ShadowChicken_Packet_codeBlock, OBJECT_OFFSETOF(ShadowChicken::Packet, codeBlock)) \
macro(ShadowChicken_Packet_callSiteIndex, OBJECT_OFFSETOF(ShadowChicken::Packet, callSiteIndex)) \
- macro(ScopedArguments_overrodeThings, ScopedArguments::offsetOfOverrodeThings()) \
+ macro(ScopedArguments_Storage_overrodeThings, ScopedArguments::offsetOfOverrodeThingsInStorage()) \
+ macro(ScopedArguments_Storage_totalLength, ScopedArguments::offsetOfTotalLengthInStorage()) \
+ macro(ScopedArguments_storage, ScopedArguments::offsetOfStorage()) \
macro(ScopedArguments_scope, ScopedArguments::offsetOfScope()) \
macro(ScopedArguments_table, ScopedArguments::offsetOfTable()) \
- macro(ScopedArguments_totalLength, ScopedArguments::offsetOfTotalLength()) \
macro(ScopedArgumentsTable_arguments, ScopedArgumentsTable::offsetOfArguments()) \
macro(ScopedArgumentsTable_length, ScopedArgumentsTable::offsetOfLength()) \
macro(StringImpl_data, StringImpl::dataOffset()) \
@@ -138,7 +139,7 @@
macro(JSLexicalEnvironment_variables, JSLexicalEnvironment::offsetOfVariables(), sizeof(EncodedJSValue)) \
macro(JSPropertyNameEnumerator_cachedPropertyNamesVectorContents, 0, sizeof(WriteBarrier<JSString>)) \
macro(JSRopeString_fibers, JSRopeString::offsetOfFibers(), sizeof(WriteBarrier<JSString>)) \
- macro(ScopedArguments_overflowStorage, ScopedArguments::overflowStorageOffset(), sizeof(EncodedJSValue)) \
+ macro(ScopedArguments_Storage_storage, 0, sizeof(EncodedJSValue)) \
macro(WriteBarrierBuffer_bufferContents, 0, sizeof(JSCell*)) \
macro(characters8, 0, sizeof(LChar)) \
macro(characters16, 0, sizeof(UChar)) \
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -3682,10 +3682,13 @@
case Array::ScopedArguments: {
LValue arguments = lowCell(m_node->child1());
+ LValue storage = m_out.bitXor(
+ m_out.loadPtr(arguments, m_heaps.ScopedArguments_storage),
+ m_out.constIntPtr(ScopedArgumentsPoison::key()));
speculate(
ExoticObjectMode, noValue(), nullptr,
- m_out.notZero32(m_out.load8ZeroExt32(arguments, m_heaps.ScopedArguments_overrodeThings)));
- setInt32(m_out.load32NonNegative(arguments, m_heaps.ScopedArguments_totalLength));
+ m_out.notZero32(m_out.load8ZeroExt32(storage, m_heaps.ScopedArguments_Storage_overrodeThings)));
+ setInt32(m_out.load32NonNegative(storage, m_heaps.ScopedArguments_Storage_totalLength));
return;
}
@@ -3883,13 +3886,18 @@
LValue base = lowCell(m_graph.varArgChild(m_node, 0));
LValue index = lowInt32(m_graph.varArgChild(m_node, 1));
+ LValue storage = m_out.loadPtr(base, m_heaps.ScopedArguments_storage);
+ storage = m_out.bitXor(storage, m_out.constIntPtr(ScopedArgumentsPoison::key()));
+
+ LValue totalLength = m_out.load32NonNegative(
+ storage, m_heaps.ScopedArguments_Storage_totalLength);
speculate(
ExoticObjectMode, noValue(), nullptr,
- m_out.aboveOrEqual(
- index,
- m_out.load32NonNegative(base, m_heaps.ScopedArguments_totalLength)));
+ m_out.aboveOrEqual(index, totalLength));
LValue table = m_out.loadPtr(base, m_heaps.ScopedArguments_table);
+ table = m_out.bitXor(table, m_out.constIntPtr(ScopedArgumentsPoison::key()));
+
LValue namedLength = m_out.load32(table, m_heaps.ScopedArgumentsTable_length);
LBasicBlock namedCase = m_out.newBlock();
@@ -3902,6 +3910,8 @@
LBasicBlock lastNext = m_out.appendTo(namedCase, overflowCase);
LValue scope = m_out.loadPtr(base, m_heaps.ScopedArguments_scope);
+ scope = m_out.bitXor(scope, m_out.constIntPtr(ScopedArgumentsPoison::key()));
+
LValue arguments = m_out.loadPtr(table, m_heaps.ScopedArgumentsTable_arguments);
TypedPointer address = m_out.baseIndex(
@@ -3920,7 +3930,7 @@
m_out.appendTo(overflowCase, continuation);
address = m_out.baseIndex(
- m_heaps.ScopedArguments_overflowStorage, base,
+ m_heaps.ScopedArguments_Storage_storage, storage,
m_out.zeroExtPtr(m_out.sub(index, namedLength)));
LValue overflowValue = m_out.load64(address);
speculate(ExoticObjectMode, noValue(), nullptr, m_out.isZero64(overflowValue));
@@ -3928,7 +3938,11 @@
m_out.jump(continuation);
m_out.appendTo(continuation, lastNext);
- setJSValue(m_out.phi(Int64, namedResult, overflowResult));
+
+ LValue result = m_out.phi(Int64, namedResult, overflowResult);
+ result = preciseIndexMask32(result, index, totalLength);
+
+ setJSValue(result);
return;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLOperations.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/ftl/FTLOperations.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/ftl/FTLOperations.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -336,7 +336,7 @@
unsigned capacity = std::max(length, static_cast<unsigned>(codeBlock->numParameters() - 1));
DirectArguments* result = DirectArguments::create(
vm, codeBlock->globalObject()->directArgumentsStructure(), length, capacity);
- result->callee().set(vm, result, callee);
+ result->setCallee(vm, callee);
for (unsigned i = materialization->properties().size(); i--;) {
const ExitPropertyValue& property = materialization->properties()[i];
if (property.location().kind() != ArgumentPLoc)
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1441,6 +1441,7 @@
JSValueRegs result = JSValueRegs(regT0);
RegisterID scratch = regT3;
RegisterID scratch2 = regT4;
+ RegisterID scratch3 = regT5;
#else
RegisterID base = regT0;
RegisterID property = regT2;
@@ -1447,16 +1448,21 @@
JSValueRegs result = JSValueRegs(regT1, regT0);
RegisterID scratch = regT3;
RegisterID scratch2 = regT4;
+ RegisterID scratch3 = regT5;
#endif
load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
badType = patchableBranch32(NotEqual, scratch, TrustedImm32(ScopedArgumentsType));
- slowCases.append(branch32(AboveOrEqual, property, Address(base, ScopedArguments::offsetOfTotalLength())));
+ loadPtr(Address(base, ScopedArguments::offsetOfStorage()), scratch3);
+ xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), scratch3);
+ slowCases.append(branch32(AboveOrEqual, property, Address(scratch3, ScopedArguments::offsetOfTotalLengthInStorage())));
loadPtr(Address(base, ScopedArguments::offsetOfTable()), scratch);
+ xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), scratch);
load32(Address(scratch, ScopedArgumentsTable::offsetOfLength()), scratch2);
Jump overflowCase = branch32(AboveOrEqual, property, scratch2);
loadPtr(Address(base, ScopedArguments::offsetOfScope()), scratch2);
+ xorPtr(TrustedImmPtr(ScopedArgumentsPoison::key()), scratch2);
loadPtr(Address(scratch, ScopedArgumentsTable::offsetOfArguments()), scratch);
load32(BaseIndex(scratch, property, TimesFour), scratch);
slowCases.append(branch32(Equal, scratch, TrustedImm32(ScopeOffset::invalidOffset)));
@@ -1465,10 +1471,14 @@
overflowCase.link(this);
sub32(property, scratch2);
neg32(scratch2);
- loadValue(BaseIndex(base, scratch2, TimesEight, ScopedArguments::overflowStorageOffset()), result);
+ loadValue(BaseIndex(scratch3, scratch2, TimesEight), result);
slowCases.append(branchIfEmpty(result));
done.link(this);
+ load32(Address(scratch3, ScopedArguments::offsetOfTotalLengthInStorage()), scratch);
+ emitPreparePreciseIndexMask32(property, scratch, scratch2);
+ andPtr(scratch2, result.payloadGPR());
+
return slowCases;
}
Modified: trunk/Source/_javascript_Core/runtime/DirectArguments.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/runtime/DirectArguments.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/runtime/DirectArguments.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -85,7 +85,7 @@
for (unsigned i = capacity; i--;)
storage[i].set(vm, result, exec->getArgumentUnsafe(i));
- result->callee().set(vm, result, jsCast<JSFunction*>(exec->jsCallee()));
+ result->setCallee(vm, jsCast<JSFunction*>(exec->jsCallee()));
return result;
}
Modified: trunk/Source/_javascript_Core/runtime/DirectArguments.h (229841 => 229842)
--- trunk/Source/_javascript_Core/runtime/DirectArguments.h 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/runtime/DirectArguments.h 2018-03-22 02:15:44 UTC (rev 229842)
@@ -110,11 +110,16 @@
preciseIndexMaskPtr(i, storageHeader(storage).length, ptr)->set(vm, this, value);
}
- WriteBarrier<JSFunction>& callee()
+ JSFunction* callee()
{
- return m_callee;
+ return m_callee.get();
}
+ void setCallee(VM& vm, JSFunction* function)
+ {
+ m_callee.set(vm, this, function);
+ }
+
WriteBarrier<Unknown>& argument(DirectArgumentsOffset offset)
{
ASSERT(offset);
Modified: trunk/Source/_javascript_Core/runtime/GenericArgumentsInlines.h (229841 => 229842)
--- trunk/Source/_javascript_Core/runtime/GenericArgumentsInlines.h 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/runtime/GenericArgumentsInlines.h 2018-03-22 02:15:44 UTC (rev 229842)
@@ -52,7 +52,7 @@
return true;
}
if (ident == vm.propertyNames->callee) {
- slot.setValue(thisObject, static_cast<unsigned>(PropertyAttribute::DontEnum), thisObject->callee().get());
+ slot.setValue(thisObject, static_cast<unsigned>(PropertyAttribute::DontEnum), thisObject->callee());
return true;
}
if (ident == vm.propertyNames->iteratorSymbol) {
Modified: trunk/Source/_javascript_Core/runtime/JSCPoison.h (229841 => 229842)
--- trunk/Source/_javascript_Core/runtime/JSCPoison.h 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/runtime/JSCPoison.h 2018-03-22 02:15:44 UTC (rev 229842)
@@ -50,6 +50,7 @@
v(JSWebAssemblyModule) \
v(JSWebAssemblyTable) \
v(NativeCode) \
+ v(ScopedArguments) \
v(StructureTransitionTable) \
v(UnlinkedSourceCode) \
v(WebAssemblyFunctionBase) \
Modified: trunk/Source/_javascript_Core/runtime/ScopedArguments.cpp (229841 => 229842)
--- trunk/Source/_javascript_Core/runtime/ScopedArguments.cpp 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/runtime/ScopedArguments.cpp 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -35,11 +35,11 @@
const ClassInfo ScopedArguments::s_info = { "Arguments", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ScopedArguments) };
-ScopedArguments::ScopedArguments(VM& vm, Structure* structure, unsigned totalLength)
+ScopedArguments::ScopedArguments(VM& vm, Structure* structure, WriteBarrier<Unknown>* storage)
: GenericArguments(vm, structure)
- , m_overrodeThings(false)
- , m_totalLength(totalLength)
+ , m_storage(vm, this, storage)
{
+ ASSERT(!storageHeader(storage).overrodeThings);
}
void ScopedArguments::finishCreation(VM& vm, JSFunction* callee, ScopedArgumentsTable* table, JSLexicalEnvironment* scope)
@@ -57,10 +57,17 @@
overflowLength = totalLength - table->length();
else
overflowLength = 0;
+
+ void* rawStoragePtr = vm.jsValueGigacageAuxiliarySpace.allocateNonVirtual(
+ vm, storageSize(overflowLength), nullptr, AllocationFailureMode::Assert);
+ WriteBarrier<Unknown>* storage = static_cast<WriteBarrier<Unknown>*>(rawStoragePtr) + 1;
+ storageHeader(storage).overrodeThings = false;
+ storageHeader(storage).totalLength = totalLength;
+
ScopedArguments* result = new (
NotNull,
- allocateCell<ScopedArguments>(vm.heap, allocationSize(overflowLength)))
- ScopedArguments(vm, structure, totalLength);
+ allocateCell<ScopedArguments>(vm.heap))
+ ScopedArguments(vm, structure, storage);
result->finishCreation(vm, callee, table, scope);
return result;
}
@@ -107,9 +114,11 @@
visitor.append(thisObject->m_table);
visitor.append(thisObject->m_scope);
- if (thisObject->m_totalLength > thisObject->m_table->length()) {
+ visitor.markAuxiliary(&thisObject->storageHeader());
+
+ if (thisObject->storageHeader().totalLength > thisObject->m_table->length()) {
visitor.appendValues(
- thisObject->overflowStorage(), thisObject->m_totalLength - thisObject->m_table->length());
+ thisObject->overflowStorage(), thisObject->storageHeader().totalLength - thisObject->m_table->length());
}
GenericArguments<ScopedArguments>::visitChildren(cell, visitor);
@@ -122,24 +131,24 @@
void ScopedArguments::overrideThings(VM& vm)
{
- RELEASE_ASSERT(!m_overrodeThings);
+ RELEASE_ASSERT(!storageHeader().overrodeThings);
putDirect(vm, vm.propertyNames->length, jsNumber(m_table->length()), static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirect(vm, vm.propertyNames->callee, m_callee.get(), static_cast<unsigned>(PropertyAttribute::DontEnum));
putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), static_cast<unsigned>(PropertyAttribute::DontEnum));
- m_overrodeThings = true;
+ storageHeader().overrodeThings = true;
}
void ScopedArguments::overrideThingsIfNecessary(VM& vm)
{
- if (!m_overrodeThings)
+ if (!storageHeader().overrodeThings)
overrideThings(vm);
}
void ScopedArguments::unmapArgument(VM& vm, uint32_t i)
{
- ASSERT_WITH_SECURITY_IMPLICATION(i < m_totalLength);
+ ASSERT_WITH_SECURITY_IMPLICATION(i < storageHeader().totalLength);
unsigned namedLength = m_table->length();
if (i < namedLength)
m_table.set(vm, this, m_table->set(vm, i, ScopeOffset()));
Modified: trunk/Source/_javascript_Core/runtime/ScopedArguments.h (229841 => 229842)
--- trunk/Source/_javascript_Core/runtime/ScopedArguments.h 2018-03-22 01:49:27 UTC (rev 229841)
+++ trunk/Source/_javascript_Core/runtime/ScopedArguments.h 2018-03-22 02:15:44 UTC (rev 229842)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -38,7 +38,7 @@
// lookups.
class ScopedArguments final : public GenericArguments<ScopedArguments> {
private:
- ScopedArguments(VM&, Structure*, unsigned totalLength);
+ ScopedArguments(VM&, Structure*, WriteBarrier<Unknown>* storage);
void finishCreation(VM&, JSFunction* callee, ScopedArgumentsTable*, JSLexicalEnvironment*);
public:
@@ -67,13 +67,13 @@
uint32_t internalLength() const
{
- return m_totalLength;
+ return storageHeader().totalLength;
}
uint32_t length(ExecState* exec) const
{
VM& vm = exec->vm();
- if (UNLIKELY(m_overrodeThings))
+ if (UNLIKELY(storageHeader().overrodeThings))
return get(exec, vm.propertyNames->length).toUInt32(exec);
return internalLength();
}
@@ -80,12 +80,13 @@
bool isMappedArgument(uint32_t i) const
{
- if (i >= m_totalLength)
+ WriteBarrier<Unknown>* storage = overflowStorage();
+ if (i >= storageHeader(storage).totalLength)
return false;
unsigned namedLength = m_table->length();
if (i < namedLength)
return !!m_table->get(i);
- return !!overflowStorage()[i - namedLength].get();
+ return !!storage[i - namedLength].get();
}
bool isMappedArgumentInDFG(uint32_t i) const
@@ -96,28 +97,32 @@
JSValue getIndexQuickly(uint32_t i) const
{
ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
+ WriteBarrier<Unknown>* storage = overflowStorage();
+ unsigned totalLength = storageHeader(storage).totalLength;
unsigned namedLength = m_table->length();
if (i < namedLength)
- return m_scope->variableAt(m_table->get(i)).get();
- return overflowStorage()[i - namedLength].get();
+ return preciseIndexMaskPtr(i, totalLength, &m_scope->variableAt(m_table->get(i)))->get();
+ return preciseIndexMaskPtr(i, totalLength, storage + (i - namedLength))->get();
}
void setIndexQuickly(VM& vm, uint32_t i, JSValue value)
{
ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
+ WriteBarrier<Unknown>* storage = overflowStorage();
+ unsigned totalLength = storageHeader(storage).totalLength;
unsigned namedLength = m_table->length();
if (i < namedLength)
- m_scope->variableAt(m_table->get(i)).set(vm, m_scope.get(), value);
+ preciseIndexMaskPtr(i, totalLength, &m_scope->variableAt(m_table->get(i)))->set(vm, m_scope.get(), value);
else
- overflowStorage()[i - namedLength].set(vm, this, value);
+ preciseIndexMaskPtr(i, totalLength, storage + (i - namedLength))->set(vm, this, value);
}
- WriteBarrier<JSFunction>& callee()
+ JSFunction* callee()
{
- return m_callee;
+ return m_callee.get();
}
- bool overrodeThings() const { return m_overrodeThings; }
+ bool overrodeThings() const { return storageHeader().overrodeThings; }
void overrideThings(VM&);
void overrideThingsIfNecessary(VM&);
void unmapArgument(VM&, uint32_t index);
@@ -143,32 +148,55 @@
static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
- static ptrdiff_t offsetOfOverrodeThings() { return OBJECT_OFFSETOF(ScopedArguments, m_overrodeThings); }
- static ptrdiff_t offsetOfTotalLength() { return OBJECT_OFFSETOF(ScopedArguments, m_totalLength); }
+ static ptrdiff_t offsetOfStorage() { return OBJECT_OFFSETOF(ScopedArguments, m_storage); }
+ static ptrdiff_t offsetOfOverrodeThingsInStorage() { return OBJECT_OFFSETOF(StorageHeader, overrodeThings) - sizeof(WriteBarrier<Unknown>); }
+ static ptrdiff_t offsetOfTotalLengthInStorage() { return OBJECT_OFFSETOF(StorageHeader, totalLength) - sizeof(WriteBarrier<Unknown>); }
static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(ScopedArguments, m_table); }
static ptrdiff_t offsetOfScope() { return OBJECT_OFFSETOF(ScopedArguments, m_scope); }
- static size_t overflowStorageOffset()
+ static size_t allocationSize(size_t inlineSize)
{
- return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(ScopedArguments));
+ RELEASE_ASSERT(!inlineSize);
+ return sizeof(ScopedArguments);
}
- static size_t allocationSize(Checked<size_t> overflowArgumentsLength)
+ static size_t storageSize(Checked<size_t> capacity)
{
- return (overflowStorageOffset() + sizeof(WriteBarrier<Unknown>) * overflowArgumentsLength).unsafeGet();
+ return (sizeof(WriteBarrier<Unknown>) * (capacity + static_cast<size_t>(1))).unsafeGet();
}
-
+
+ static size_t storageHeaderSize() { return sizeof(WriteBarrier<Unknown>); }
+
private:
+ struct StorageHeader {
+ unsigned totalLength;
+ bool overrodeThings; // True if length, callee, and caller are fully materialized in the object.
+ };
+
WriteBarrier<Unknown>* overflowStorage() const
{
- return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(this) + overflowStorageOffset());
+ return m_storage.get().unpoisoned();
}
- bool m_overrodeThings; // True if length, callee, and caller are fully materialized in the object.
- unsigned m_totalLength; // The length of declared plus overflow arguments.
- WriteBarrier<JSFunction> m_callee;
- WriteBarrier<ScopedArgumentsTable> m_table;
- WriteBarrier<JSLexicalEnvironment> m_scope;
+ static StorageHeader& storageHeader(WriteBarrier<Unknown>* storage)
+ {
+ static_assert(sizeof(StorageHeader) <= sizeof(WriteBarrier<Unknown>), "StorageHeader needs to be no bigger than a JSValue");
+ return *bitwise_cast<StorageHeader*>(storage - 1);
+ }
+
+ StorageHeader& storageHeader() const
+ {
+ return storageHeader(overflowStorage());
+ }
+
+ template<typename T>
+ using PoisonedBarrier = PoisonedWriteBarrier<ScopedArgumentsPoison, T>;
+
+ PoisonedBarrier<JSFunction> m_callee;
+ PoisonedBarrier<ScopedArgumentsTable> m_table;
+ PoisonedBarrier<JSLexicalEnvironment> m_scope;
+
+ AuxiliaryBarrier<Poisoned<ScopedArgumentsPoison, WriteBarrier<Unknown>*>> m_storage;
};
} // namespace JSC