Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (113135 => 113136)
--- trunk/Source/_javascript_Core/ChangeLog 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1,3 +1,41 @@
+2012-04-02 Filip Pizlo <[email protected]>
+
+ jsr/sret should be removed
+ https://bugs.webkit.org/show_bug.cgi?id=82986
+ <rdar://problem/11017015>
+
+ Reviewed by Sam Weinig and Geoff Garen.
+
+ Replaces jsr/sret with finally block inlining.
+
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dump):
+ * bytecode/Opcode.h:
+ (JSC):
+ (JSC::padOpcodeName):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::pushFinallyContext):
+ (JSC::BytecodeGenerator::emitComplexJumpScopes):
+ (JSC):
+ * bytecompiler/BytecodeGenerator.h:
+ (FinallyContext):
+ (BytecodeGenerator):
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::TryNode::emitBytecode):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::privateExecute):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompile):
+ * jit/JIT.h:
+ (JIT):
+ * jit/JITOpcodes.cpp:
+ (JSC):
+ * jit/JITOpcodes32_64.cpp:
+ (JSC):
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+
2012-04-03 Mark Rowe <[email protected]>
Make it possible to install the _javascript_Core test tools.
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1248,17 +1248,6 @@
dataLog("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data());
break;
}
- case op_jsr: {
- int retAddrDst = (++it)->u.operand;
- int offset = (++it)->u.operand;
- dataLog("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).data(), offset, location + offset);
- break;
- }
- case op_sret: {
- int retAddrSrc = (++it)->u.operand;
- dataLog("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data());
- break;
- }
case op_debug: {
int debugHookID = (++it)->u.operand;
int firstLine = (++it)->u.operand;
Modified: trunk/Source/_javascript_Core/bytecode/Opcode.h (113135 => 113136)
--- trunk/Source/_javascript_Core/bytecode/Opcode.h 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/bytecode/Opcode.h 2012-04-04 04:25:56 UTC (rev 113136)
@@ -189,9 +189,6 @@
macro(op_throw, 2) \
macro(op_throw_reference_error, 2) \
\
- macro(op_jsr, 3) \
- macro(op_sret, 2) \
- \
macro(op_debug, 4) \
macro(op_profile_will_call, 2) \
macro(op_profile_did_call, 2) \
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <[email protected]>
* Copyright (C) 2012 Igalia, S.L.
*
@@ -2004,11 +2004,19 @@
instructions().append(lastLine);
}
-void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst)
+void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock)
{
ControlFlowContext scope;
scope.isFinallyBlock = true;
- FinallyContext context = { target, retAddrDst };
+ FinallyContext context = {
+ finallyBlock,
+ m_scopeContextStack.size(),
+ m_switchContextStack.size(),
+ m_forInContextStack.size(),
+ m_labelScopes.size(),
+ m_finallyDepth,
+ m_dynamicScopeDepth
+ };
scope.finallyContext = context;
m_scopeContextStack.append(scope);
m_finallyDepth++;
@@ -2134,9 +2142,63 @@
instructions().append(nextInsn->bind(begin, instructions().size()));
emitLabel(nextInsn.get());
}
-
+
+ Vector<ControlFlowContext> savedScopeContextStack;
+ Vector<SwitchInfo> savedSwitchContextStack;
+ Vector<ForInContext> savedForInContextStack;
+ SegmentedVector<LabelScope, 8> savedLabelScopes;
while (topScope > bottomScope && topScope->isFinallyBlock) {
- emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
+ // Save the current state of the world while instating the state of the world
+ // for the finally block.
+ FinallyContext finallyContext = topScope->finallyContext;
+ bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size();
+ bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size();
+ bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size();
+ bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size();
+ int topScopeIndex = -1;
+ int bottomScopeIndex = -1;
+ if (flipScopes) {
+ topScopeIndex = topScope - m_scopeContextStack.begin();
+ bottomScopeIndex = bottomScope - m_scopeContextStack.begin();
+ savedScopeContextStack = m_scopeContextStack;
+ m_scopeContextStack.shrink(finallyContext.scopeContextStackSize);
+ }
+ if (flipSwitches) {
+ savedSwitchContextStack = m_switchContextStack;
+ m_switchContextStack.shrink(finallyContext.switchContextStackSize);
+ }
+ if (flipForIns) {
+ savedForInContextStack = m_forInContextStack;
+ m_forInContextStack.shrink(finallyContext.forInContextStackSize);
+ }
+ if (flipLabelScopes) {
+ savedLabelScopes = m_labelScopes;
+ while (m_labelScopes.size() > finallyContext.labelScopesSize)
+ m_labelScopes.removeLast();
+ }
+ int savedFinallyDepth = m_finallyDepth;
+ m_finallyDepth = finallyContext.finallyDepth;
+ int savedDynamicScopeDepth = m_dynamicScopeDepth;
+ m_dynamicScopeDepth = finallyContext.dynamicScopeDepth;
+
+ // Emit the finally block.
+ emitNode(finallyContext.finallyBlock);
+
+ // Restore the state of the world.
+ if (flipScopes) {
+ m_scopeContextStack = savedScopeContextStack;
+ topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds
+ bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1.
+ }
+ if (flipSwitches)
+ m_switchContextStack = savedSwitchContextStack;
+ if (flipForIns)
+ m_forInContextStack = savedForInContextStack;
+ if (flipLabelScopes)
+ m_labelScopes = savedLabelScopes;
+ m_finallyDepth = savedFinallyDepth;
+ m_dynamicScopeDepth = savedDynamicScopeDepth;
+
--topScope;
}
}
@@ -2216,23 +2278,6 @@
instructions().append(addConstantValue(jsString(globalData(), message))->index());
}
-PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
-{
- size_t begin = instructions().size();
-
- emitOpcode(op_jsr);
- instructions().append(retAddrDst->index());
- instructions().append(finally->bind(begin, instructions().size()));
- emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
- return finally;
-}
-
-void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
-{
- emitOpcode(op_sret);
- instructions().append(retAddrSrc->index());
-}
-
void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
{
ControlFlowContext context;
Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (113135 => 113136)
--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2008 Cameron Zwarich <[email protected]>
* Copyright (C) 2012 Igalia, S.L.
*
@@ -71,8 +71,13 @@
};
struct FinallyContext {
- Label* finallyAddr;
- RegisterID* retAddrDst;
+ StatementNode* finallyBlock;
+ unsigned scopeContextStackSize;
+ unsigned switchContextStackSize;
+ unsigned forInContextStackSize;
+ unsigned labelScopesSize;
+ int finallyDepth;
+ int dynamicScopeDepth;
};
struct ControlFlowContext {
@@ -479,9 +484,6 @@
PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
- PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
- void emitSubroutineReturn(RegisterID* retAddrSrc);
-
RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
@@ -504,7 +506,7 @@
int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
bool hasFinaliser() { return m_finallyDepth != 0; }
- void pushFinallyContext(Label* target, RegisterID* returnAddrDst);
+ void pushFinallyContext(StatementNode* finallyBlock);
void popFinallyContext();
void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2002 Harri Porten ([email protected])
* Copyright (C) 2001 Peter Kelly ([email protected])
-* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
* Copyright (C) 2007 Cameron Zwarich ([email protected])
* Copyright (C) 2007 Maks Orlovich
* Copyright (C) 2007 Eric Seidel <[email protected]>
@@ -1727,7 +1727,7 @@
RefPtr<RegisterID> returnRegister;
if (generator.scopeDepth()) {
RefPtr<Label> l0 = generator.newLabel();
- if (generator.hasFinaliser() && !r0->isTemporary()) {
+ if (generator.hasFinaliser()) {
returnRegister = generator.emitMove(generator.newTemporary(), r0);
r0 = returnRegister.get();
}
@@ -1957,13 +1957,8 @@
generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine());
RefPtr<Label> tryStartLabel = generator.newLabel();
- RefPtr<Label> finallyStart;
- RefPtr<RegisterID> finallyReturnAddr;
- if (m_finallyBlock) {
- finallyStart = generator.newLabel();
- finallyReturnAddr = generator.newTemporary();
- generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get());
- }
+ if (m_finallyBlock)
+ generator.pushFinallyContext(m_finallyBlock);
generator.emitLabel(tryStartLabel.get());
generator.emitNode(dst, m_tryBlock);
@@ -1985,28 +1980,19 @@
if (m_finallyBlock) {
generator.popFinallyContext();
- // there may be important registers live at the time we jump
- // to a finally block (such as for a return or throw) so we
- // ref the highest register ever used as a conservative
- // approach to not clobbering anything important
- RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister();
+
RefPtr<Label> finallyEndLabel = generator.newLabel();
- // Normal path: invoke the finally block, then jump over it.
- generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ // Normal path: run the finally code, and jump to the end.
+ generator.emitNode(dst, m_finallyBlock);
generator.emitJump(finallyEndLabel.get());
// Uncaught exception path: invoke the finally block, then re-throw the exception.
RefPtr<Label> here = generator.emitLabel(generator.newLabel().get());
RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get());
- generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get());
+ generator.emitNode(dst, m_finallyBlock);
generator.emitThrow(tempExceptionRegister.get());
- // The finally block.
- generator.emitLabel(finallyStart.get());
- generator.emitNode(dst, m_finallyBlock);
- generator.emitSubroutineReturn(finallyReturnAddr.get());
-
generator.emitLabel(finallyEndLabel.get());
}
Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -5186,30 +5186,6 @@
vPC++;
NEXT_INSTRUCTION();
}
- DEFINE_OPCODE(op_jsr) {
- /* jsr retAddrDst(r) target(offset)
-
- Places the address of the next instruction into the retAddrDst
- register and jumps to offset target from the current instruction.
- */
- int retAddrDst = vPC[1].u.operand;
- int target = vPC[2].u.operand;
- callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr);
-
- vPC += target;
- NEXT_INSTRUCTION();
- }
- DEFINE_OPCODE(op_sret) {
- /* sret retAddrSrc(r)
-
- Jumps to the address stored in the retAddrSrc register. This
- differs from op_jmp because the target address is stored in a
- register, not as an immediate.
- */
- int retAddrSrc = vPC[1].u.operand;
- vPC = callFrame->r(retAddrSrc).vPC();
- NEXT_INSTRUCTION();
- }
DEFINE_OPCODE(op_debug) {
/* debug debugHookID(n) firstLine(n) lastLine(n)
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -283,7 +283,6 @@
DEFINE_OP(op_jnlesseq)
DEFINE_OP(op_jngreater)
DEFINE_OP(op_jngreatereq)
- DEFINE_OP(op_jsr)
DEFINE_OP(op_jtrue)
DEFINE_OP(op_loop)
DEFINE_OP(op_loop_hint)
@@ -340,7 +339,6 @@
DEFINE_OP(op_ret_object_or_this)
DEFINE_OP(op_rshift)
DEFINE_OP(op_urshift)
- DEFINE_OP(op_sret)
DEFINE_OP(op_strcat)
DEFINE_OP(op_stricteq)
DEFINE_OP(op_sub)
@@ -665,10 +663,6 @@
m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset));
}
- // Link absolute addresses for jsr
- for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
- patchBuffer.patch(iter->storeLocation, patchBuffer.locationOf(iter->target).executableAddress());
-
m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccessCompilationInfo.size());
for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i) {
StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
Modified: trunk/Source/_javascript_Core/jit/JIT.h (113135 => 113136)
--- trunk/Source/_javascript_Core/jit/JIT.h 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2012-04-04 04:25:56 UTC (rev 113136)
@@ -280,17 +280,6 @@
static void linkFor(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, JSGlobalData*, CodeSpecializationKind);
private:
- struct JSRInfo {
- DataLabelPtr storeLocation;
- Label target;
-
- JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
- : storeLocation(storeLocation)
- , target(targetLocation)
- {
- }
- };
-
JIT(JSGlobalData*, CodeBlock* = 0);
void privateCompileMainPass();
@@ -829,7 +818,6 @@
void emit_op_jnlesseq(Instruction*);
void emit_op_jngreater(Instruction*);
void emit_op_jngreatereq(Instruction*);
- void emit_op_jsr(Instruction*);
void emit_op_jtrue(Instruction*);
void emit_op_loop(Instruction*);
void emit_op_loop_hint(Instruction*);
@@ -883,7 +871,6 @@
void emit_op_ret(Instruction*);
void emit_op_ret_object_or_this(Instruction*);
void emit_op_rshift(Instruction*);
- void emit_op_sret(Instruction*);
void emit_op_strcat(Instruction*);
void emit_op_stricteq(Instruction*);
void emit_op_sub(Instruction*);
@@ -1066,7 +1053,6 @@
Vector<JumpTable> m_jmpTable;
unsigned m_bytecodeOffset;
- Vector<JSRInfo> m_jsrSites;
Vector<SlowCaseEntry> m_slowCases;
Vector<SwitchRecord> m_switches;
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -742,22 +742,6 @@
addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target);
}
-void JIT::emit_op_jsr(Instruction* currentInstruction)
-{
- int retAddrDst = currentInstruction[1].u.operand;
- int target = currentInstruction[2].u.operand;
- DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
- addJump(jump(), target);
- m_jsrSites.append(JSRInfo(storeLocation, label()));
- killLastResultRegister();
-}
-
-void JIT::emit_op_sret(Instruction* currentInstruction)
-{
- jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
- killLastResultRegister();
-}
-
void JIT::emit_op_eq(Instruction* currentInstruction)
{
emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
Modified: trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp (113135 => 113136)
--- trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/jit/JITOpcodes32_64.cpp 2012-04-04 04:25:56 UTC (rev 113136)
@@ -921,20 +921,6 @@
addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target);
}
-void JIT::emit_op_jsr(Instruction* currentInstruction)
-{
- int retAddrDst = currentInstruction[1].u.operand;
- int target = currentInstruction[2].u.operand;
- DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
- addJump(jump(), target);
- m_jsrSites.append(JSRInfo(storeLocation, label()));
-}
-
-void JIT::emit_op_sret(Instruction* currentInstruction)
-{
- jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
-}
-
void JIT::emit_op_eq(Instruction* currentInstruction)
{
unsigned dst = currentInstruction[1].u.operand;
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (113135 => 113136)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1571,21 +1571,6 @@
dispatch(2)
-_llint_op_jsr:
- traceExecution()
- loadi 4[PC], t0
- addi 3 * 4, PC, t1
- storei t1, [cfr, t0, 8]
- dispatchBranch(8[PC])
-
-
-_llint_op_sret:
- traceExecution()
- loadi 4[PC], t0
- loadp [cfr, t0, 8], PC
- dispatch(0)
-
-
_llint_op_end:
traceExecution()
checkSwitchToJITForEpilogue()
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (113135 => 113136)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2012-04-04 04:21:15 UTC (rev 113135)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2012-04-04 04:25:56 UTC (rev 113136)
@@ -1429,21 +1429,6 @@
dispatch(2)
-_llint_op_jsr:
- traceExecution()
- loadis 8[PB, PC, 8], t0
- addi 3, PC, t1
- storei t1, [cfr, t0, 8]
- dispatchInt(16[PB, PC, 8])
-
-
-_llint_op_sret:
- traceExecution()
- loadis 8[PB, PC, 8], t0
- loadi [cfr, t0, 8], PC
- dispatch(0)
-
-
_llint_op_end:
traceExecution()
checkSwitchToJITForEpilogue()