<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[189938] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/189938">189938</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2015-09-17 15:02:54 -0700 (Thu, 17 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement try/catch in the DFG.
https://bugs.webkit.org/show_bug.cgi?id=147374

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch implements try/catch inside the DFG JIT.
It also prevents tier up to the FTL for any functions
that have an op_catch in them that are DFG compiled.

This patch accomplishes implementing try/catch inside
the DFG by OSR exiting to op_catch when an exception is thrown.
We can OSR exit from an exception inside the DFG in two ways:
1) We have a JS call (can also be via implicit getter/setter in GetById/PutById)
2) We have an exception when returing from a callOperation

In the case of (1), we get to the OSR exit from genericUnwind because
the exception was thrown in a child call frame. This means these
OSR exits must act as defacto op_catches (even though we will still OSR
exit to a baseline op_catch). That means they must restore the stack pointer
and call frame.

In the case of (2), we can skip genericUnwind because we know the exception 
check will take us to a particular OSR exit. Instead, we link these
exception checks as jumps to a particular OSR exit.

Both types of OSR exits will exit into op_catch inside the baseline JIT.
Because they exit to op_catch, these OSR exits must set callFrameForCatch
to the proper call frame pointer.

We &quot;handle&quot; all exceptions inside the machine frame of the DFG code
block. This means the machine code block is responsible for &quot;catching&quot;
exceptions of any inlined frames' try/catch. OSR exit will then exit to 
the proper baseline CodeBlock after reifying the inlined frames
(DFG::OSRExit::m_codeOrigin corresponds to the op_catch we will exit to). 
Also, genericUnwind will never consult an inlined call frame's CodeBlock to 
see if they can catch the exception because they can't. We always unwind to the 
next machine code block frame. The DFG CodeBlock changes how the exception 
handler table is keyed: it is now keyed by CallSiteIndex for DFG code blocks. 

So, when consulting call sites that throw, we keep track of the CallSiteIndex,
and the HandlerInfo for the corresponding baseline exception handler for
that particular CallSiteIndex (if an exception at that call site will be caught). 
Then, when we're inside DFG::JITCompiler::link(), we install new HandlerInfo's
inside the DFG CodeBlock and key it by the corresponding CallSiteIndex.
(The CodeBlock only has HandlerInfos for the OSR exits that are to be arrived
at from genericUnwind).

Also, each OSR exit will know if it acting as an exception handler, and
whether or not it will be arrived at from genericUnwind. When we know we 
will arrive at an OSR exit from genericUnwind, we set the corresponding 
HandlerInfo's nativeCode CodeLocationLabel field to be the OSR exit.

This patch also introduces a new Phase inside the DFG that ensures
that DFG CodeBlocks that handle exceptions take the necessary
steps to keep live variables at &quot;op_catch&quot; live according the
OSR exit value recovery machinery. We accomplish this by flushing
all live op_catch variables to the stack when inside a &quot;try&quot; block.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::handlerForBytecodeOffset):
(JSC::CodeBlock::handlerForIndex):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::clearExceptionHandlers):
(JSC::CodeBlock::appendExceptionHandler):
* bytecode/PreciseJumpTargets.cpp:
(JSC::computePreciseJumpTargets):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::getLocal):
(JSC::DFG::ByteCodeParser::setLocal):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGCommonData.cpp:
(JSC::DFG::CommonData::addCodeOrigin):
(JSC::DFG::CommonData::lastCallSite):
(JSC::DFG::CommonData::shrinkToFit):
* dfg/DFGCommonData.h:
* dfg/DFGGraph.h:
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::noticeOSREntry):
(JSC::DFG::JITCompiler::appendExceptionHandlingOSRExit):
(JSC::DFG::JITCompiler::willCatchExceptionInMachineFrame):
(JSC::DFG::JITCompiler::exceptionCheck):
(JSC::DFG::JITCompiler::recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::emitStoreCodeOrigin):
(JSC::DFG::JITCompiler::emitStoreCallSiteIndex):
(JSC::DFG::JITCompiler::appendCall):
(JSC::DFG::JITCompiler::exceptionCheckWithCallFrameRollback):
(JSC::DFG::JITCompiler::blockHeads):
(JSC::DFG::JITCompiler::exceptionCheck): Deleted.
* dfg/DFGLiveCatchVariablePreservationPhase.cpp: Added.
(JSC::DFG::FlushLiveCatchVariablesInsertionPhase::FlushLiveCatchVariablesInsertionPhase):
(JSC::DFG::FlushLiveCatchVariablesInsertionPhase::run):
(JSC::DFG::FlushLiveCatchVariablesInsertionPhase::willCatchException):
(JSC::DFG::FlushLiveCatchVariablesInsertionPhase::handleBlock):
(JSC::DFG::FlushLiveCatchVariablesInsertionPhase::newVariableAccessData):
(JSC::DFG::performLiveCatchVariablePreservationPhase):
* dfg/DFGLiveCatchVariablePreservationPhase.h: Added.
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::OSRExit::setPatchableCodeOffset):
* dfg/DFGOSRExit.h:
(JSC::DFG::OSRExit::considerAddingAsFrequentExitSite):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::osrWriteBarrier):
(JSC::DFG::adjustAndJumpToTarget):
* dfg/DFGOSRExitCompilerCommon.h:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGSlowPathGenerator.h:
(JSC::DFG::SlowPathGenerator::SlowPathGenerator):
(JSC::DFG::SlowPathGenerator::~SlowPathGenerator):
(JSC::DFG::SlowPathGenerator::generate):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedPutById):
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGTierUpCheckInjectionPhase.cpp:
(JSC::DFG::TierUpCheckInjectionPhase::run):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):
* interpreter/Interpreter.cpp:
(JSC::GetCatchHandlerFunctor::operator()):
(JSC::UnwindFunctor::operator()):
* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::gotoNextFrame):
(JSC::StackVisitor::unwindToMachineCodeBlockFrame):
(JSC::StackVisitor::readFrame):
* interpreter/StackVisitor.h:
(JSC::StackVisitor::operator*):
(JSC::StackVisitor::operator-&gt;):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::emitExceptionCheck):
(JSC::AssemblyHelpers::emitNonPatchableExceptionCheck):
(JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitCount):
* jit/JITExceptions.cpp:
(JSC::genericUnwind):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_catch):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_catch):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/VM.h:
(JSC::VM::clearException):
(JSC::VM::clearLastException):
(JSC::VM::addressOfCallFrameForCatch):
(JSC::VM::exception):
(JSC::VM::addressOfException):
* tests/stress/dfg-exception-try-catch-in-constructor-with-inlined-throw.js: Added.
(f):
(bar):
(Foo):
* tests/stress/es6-for-of-loop-exception.js: Added.
(assert):
(shouldThrowInvalidConstAssignment):
(baz):
(foo):
* tests/stress/exception-dfg-inlined-frame-not-strict-equal.js: Added.
(assert):
(o.valueOf):
(o.toString):
(read):
(bar):
(foo):
* tests/stress/exception-dfg-not-strict-equal.js: Added.
(foo):
(o.valueOf):
(o.toString):
(assert):
(shouldDoSomethingInFinally):
(catch):
* tests/stress/exception-dfg-operation-read-value.js: Added.
(assert):
(o.valueOf):
(o.toString):
(read):
(foo):
* tests/stress/exception-dfg-throw-from-catch-block.js: Added.
(assert):
(baz):
(bar):
(foo):

LayoutTests:

* js/regress/raytrace-with-empty-try-catch-expected.txt: Added.
* js/regress/raytrace-with-empty-try-catch.html: Added.
* js/regress/raytrace-with-try-catch-expected.txt: Added.
* js/regress/raytrace-with-try-catch.html: Added.
* js/regress/script-tests/raytrace-with-empty-try-catch.js: Added.
(createVector):
(sqrLengthVector):
(lengthVector):
(addVector):
(subVector):
(scaleVector):
(normaliseVector):
(add):
(sub):
(scalev):
(dot):
(scale):
(cross):
(normalise):
(transformMatrix):
(invertMatrix):
(Triangle):
(Triangle.prototype.intersect):
(Scene):
(Scene.prototype.intersect):
(Scene.prototype.blocked):
(Camera):
(Camera.prototype.generateRayPair):
(renderRows):
(Camera.prototype.render):
(raytraceScene.floorShader):
(raytraceScene):
(arrayToCanvasCommands):
* js/regress/script-tests/raytrace-with-try-catch.js: Added.
(randomException):
(createVector):
(sqrLengthVector):
(lengthVector):
(addVector):
(subVector):
(scaleVector):
(normaliseVector):
(add):
(sub):
(scalev):
(dot):
(scale):
(cross):
(normalise):
(transformMatrix):
(invertMatrix):
(Triangle):
(Triangle.prototype.intersect):
(Scene):
(Scene.prototype.intersect):
(Scene.prototype.blocked):
(Camera):
(Camera.prototype.generateRayPair):
(renderRows):
(Camera.prototype.render):
(raytraceScene.floorShader):
(raytraceScene):
(arrayToCanvasCommands):
* js/regress/script-tests/v8-raytrace-with-empty-try-catch.js: Added.
(Class.create):
(Object.extend):
(Flog.RayTracer.Color.prototype.initialize):
(Flog.RayTracer.Color.prototype.add):
(Flog.RayTracer.Color.prototype.addScalar):
(Flog.RayTracer.Color.prototype.subtract):
(Flog.RayTracer.Color.prototype.multiply):
(Flog.RayTracer.Color.prototype.multiplyScalar):
(Flog.RayTracer.Color.prototype.divideFactor):
(Flog.RayTracer.Color.prototype.limit):
(Flog.RayTracer.Color.prototype.distance):
(Flog.RayTracer.Color.prototype.blend):
(Flog.RayTracer.Color.prototype.brightness):
(Flog.RayTracer.Color.prototype.toString):
(Flog.RayTracer.Light.prototype.initialize):
(Flog.RayTracer.Light.prototype.toString):
(Flog.RayTracer.Vector.prototype.initialize):
(Flog.RayTracer.Vector.prototype.copy):
(Flog.RayTracer.Vector.prototype.normalize):
(Flog.RayTracer.Vector.prototype.magnitude):
(Flog.RayTracer.Vector.prototype.cross):
(Flog.RayTracer.Vector.prototype.dot):
(Flog.RayTracer.Vector.prototype.add):
(Flog.RayTracer.Vector.prototype.subtract):
(Flog.RayTracer.Vector.prototype.multiplyVector):
(Flog.RayTracer.Vector.prototype.multiplyScalar):
(Flog.RayTracer.Vector.prototype.toString):
(Flog.RayTracer.Ray.prototype.initialize):
(Flog.RayTracer.Ray.prototype.toString):
(Flog.RayTracer.Scene.prototype.initialize):
(Flog.RayTracer.Material.BaseMaterial.prototype.initialize):
(Flog.RayTracer.Material.BaseMaterial.prototype.getColor):
(Flog.RayTracer.Material.BaseMaterial.prototype.wrapUp):
(Flog.RayTracer.Material.BaseMaterial.prototype.toString):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
(Flog.RayTracer.Shape.Sphere.prototype.initialize):
(Flog.RayTracer.Shape.Sphere.prototype.intersect):
(Flog.RayTracer.Shape.Sphere.prototype.toString):
(Flog.RayTracer.Shape.Plane.prototype.initialize):
(Flog.RayTracer.Shape.Plane.prototype.intersect):
(Flog.RayTracer.Shape.Plane.prototype.toString):
(Flog.RayTracer.IntersectionInfo.prototype.initialize):
(Flog.RayTracer.IntersectionInfo.prototype.toString):
(Flog.RayTracer.Camera.prototype.initialize):
(Flog.RayTracer.Camera.prototype.getRay):
(Flog.RayTracer.Camera.prototype.toString):
(Flog.RayTracer.Background.prototype.initialize):
(Flog.RayTracer.Engine.prototype.initialize):
(Flog.RayTracer.Engine.prototype.setPixel):
(Flog.RayTracer.Engine.prototype.renderScene):
(Flog.RayTracer.Engine.prototype.getPixelColor):
(Flog.RayTracer.Engine.prototype.testIntersection):
(Flog.RayTracer.Engine.prototype.getReflectionRay):
(Flog.RayTracer.Engine.prototype.rayTrace):
(renderScene):
* js/regress/script-tests/v8-raytrace-with-try-catch.js: Added.
(randomException):
(Class.create):
(Object.extend):
(Flog.RayTracer.Color.prototype.initialize):
(Flog.RayTracer.Color.prototype.add):
(Flog.RayTracer.Color.prototype.addScalar):
(Flog.RayTracer.Color.prototype.subtract):
(Flog.RayTracer.Color.prototype.multiply):
(Flog.RayTracer.Color.prototype.multiplyScalar):
(Flog.RayTracer.Color.prototype.divideFactor):
(Flog.RayTracer.Color.prototype.limit):
(Flog.RayTracer.Color.prototype.distance):
(Flog.RayTracer.Color.prototype.blend):
(Flog.RayTracer.Color.prototype.brightness):
(Flog.RayTracer.Color.prototype.toString):
(Flog.RayTracer.Light.prototype.initialize):
(Flog.RayTracer.Light.prototype.toString):
(Flog.RayTracer.Vector.prototype.initialize):
(Flog.RayTracer.Vector.prototype.copy):
(Flog.RayTracer.Vector.prototype.normalize):
(Flog.RayTracer.Vector.prototype.magnitude):
(Flog.RayTracer.Vector.prototype.cross):
(Flog.RayTracer.Vector.prototype.dot):
(Flog.RayTracer.Vector.prototype.add):
(Flog.RayTracer.Vector.prototype.subtract):
(Flog.RayTracer.Vector.prototype.multiplyVector):
(Flog.RayTracer.Vector.prototype.multiplyScalar):
(Flog.RayTracer.Vector.prototype.toString):
(Flog.RayTracer.Ray.prototype.initialize):
(Flog.RayTracer.Ray.prototype.toString):
(Flog.RayTracer.Scene.prototype.initialize):
(Flog.RayTracer.Material.BaseMaterial.prototype.initialize):
(Flog.RayTracer.Material.BaseMaterial.prototype.getColor):
(Flog.RayTracer.Material.BaseMaterial.prototype.wrapUp):
(Flog.RayTracer.Material.BaseMaterial.prototype.toString):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
(Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
(Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
(Flog.RayTracer.Shape.Sphere.prototype.initialize):
(Flog.RayTracer.Shape.Sphere.prototype.intersect):
(Flog.RayTracer.Shape.Sphere.prototype.toString):
(Flog.RayTracer.Shape.Plane.prototype.initialize):
(Flog.RayTracer.Shape.Plane.prototype.intersect):
(Flog.RayTracer.Shape.Plane.prototype.toString):
(Flog.RayTracer.IntersectionInfo.prototype.initialize):
(Flog.RayTracer.IntersectionInfo.prototype.toString):
(Flog.RayTracer.Camera.prototype.initialize):
(Flog.RayTracer.Camera.prototype.getRay):
(Flog.RayTracer.Camera.prototype.toString):
(Flog.RayTracer.Background.prototype.initialize):
(Flog.RayTracer.Engine.prototype.initialize):
(Flog.RayTracer.Engine.prototype.setPixel):
(Flog.RayTracer.Engine.prototype.renderScene):
(Flog.RayTracer.Engine.prototype.getPixelColor):
(Flog.RayTracer.Engine.prototype.testIntersection):
(Flog.RayTracer.Engine.prototype.getReflectionRay):
(Flog.RayTracer.Engine.prototype.rayTrace):
(renderScene):
* js/regress/v8-raytrace-with-empty-try-catch-expected.txt: Added.
* js/regress/v8-raytrace-with-empty-try-catch.html: Added.
* js/regress/v8-raytrace-with-try-catch-expected.txt: Added.
* js/regress/v8-raytrace-with-try-catch.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePreciseJumpTargetscpp">trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCommonDatacpp">trunk/Source/JavaScriptCore/dfg/DFGCommonData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCommonDatah">trunk/Source/JavaScriptCore/dfg/DFGCommonData.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilerh">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitcpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExith">trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompiler32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompiler64cpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommoncpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommonh">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSlowPathGeneratorh">trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorcpp">trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorh">trunk/Source/JavaScriptCore/interpreter/StackVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelperscpp">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITExceptionscpp">trunk/Source/JavaScriptCore/jit/JITExceptions.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressraytracewithemptytrycatchexpectedtxt">trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressraytracewithemptytrycatchhtml">trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch.html</a></li>
<li><a href="#trunkLayoutTestsjsregressraytracewithtrycatchexpectedtxt">trunk/LayoutTests/js/regress/raytrace-with-try-catch-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressraytracewithtrycatchhtml">trunk/LayoutTests/js/regress/raytrace-with-try-catch.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsraytracewithemptytrycatchjs">trunk/LayoutTests/js/regress/script-tests/raytrace-with-empty-try-catch.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsraytracewithtrycatchjs">trunk/LayoutTests/js/regress/script-tests/raytrace-with-try-catch.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsv8raytracewithemptytrycatchjs">trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-empty-try-catch.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsv8raytracewithtrycatchjs">trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-try-catch.js</a></li>
<li><a href="#trunkLayoutTestsjsregressv8raytracewithemptytrycatchexpectedtxt">trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressv8raytracewithemptytrycatchhtml">trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch.html</a></li>
<li><a href="#trunkLayoutTestsjsregressv8raytracewithtrycatchexpectedtxt">trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressv8raytracewithtrycatchhtml">trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch.html</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLiveCatchVariablePreservationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLiveCatchVariablePreservationPhaseh">trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdfgexceptiontrycatchinconstructorwithinlinedthrowjs">trunk/Source/JavaScriptCore/tests/stress/dfg-exception-try-catch-in-constructor-with-inlined-throw.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresses6forofloopexceptionjs">trunk/Source/JavaScriptCore/tests/stress/es6-for-of-loop-exception.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressexceptiondfginlinedframenotstrictequaljs">trunk/Source/JavaScriptCore/tests/stress/exception-dfg-inlined-frame-not-strict-equal.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressexceptiondfgnotstrictequaljs">trunk/Source/JavaScriptCore/tests/stress/exception-dfg-not-strict-equal.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressexceptiondfgoperationreadvaluejs">trunk/Source/JavaScriptCore/tests/stress/exception-dfg-operation-read-value.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressexceptiondfgthrowfromcatchblockjs">trunk/Source/JavaScriptCore/tests/stress/exception-dfg-throw-from-catch-block.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/LayoutTests/ChangeLog        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -1,3 +1,205 @@
</span><ins>+2015-09-17  Saam barati  &lt;sbarati@apple.com&gt;
+
+        Implement try/catch in the DFG.
+        https://bugs.webkit.org/show_bug.cgi?id=147374
+
+        Reviewed by Filip Pizlo.
+
+        * js/regress/raytrace-with-empty-try-catch-expected.txt: Added.
+        * js/regress/raytrace-with-empty-try-catch.html: Added.
+        * js/regress/raytrace-with-try-catch-expected.txt: Added.
+        * js/regress/raytrace-with-try-catch.html: Added.
+        * js/regress/script-tests/raytrace-with-empty-try-catch.js: Added.
+        (createVector):
+        (sqrLengthVector):
+        (lengthVector):
+        (addVector):
+        (subVector):
+        (scaleVector):
+        (normaliseVector):
+        (add):
+        (sub):
+        (scalev):
+        (dot):
+        (scale):
+        (cross):
+        (normalise):
+        (transformMatrix):
+        (invertMatrix):
+        (Triangle):
+        (Triangle.prototype.intersect):
+        (Scene):
+        (Scene.prototype.intersect):
+        (Scene.prototype.blocked):
+        (Camera):
+        (Camera.prototype.generateRayPair):
+        (renderRows):
+        (Camera.prototype.render):
+        (raytraceScene.floorShader):
+        (raytraceScene):
+        (arrayToCanvasCommands):
+        * js/regress/script-tests/raytrace-with-try-catch.js: Added.
+        (randomException):
+        (createVector):
+        (sqrLengthVector):
+        (lengthVector):
+        (addVector):
+        (subVector):
+        (scaleVector):
+        (normaliseVector):
+        (add):
+        (sub):
+        (scalev):
+        (dot):
+        (scale):
+        (cross):
+        (normalise):
+        (transformMatrix):
+        (invertMatrix):
+        (Triangle):
+        (Triangle.prototype.intersect):
+        (Scene):
+        (Scene.prototype.intersect):
+        (Scene.prototype.blocked):
+        (Camera):
+        (Camera.prototype.generateRayPair):
+        (renderRows):
+        (Camera.prototype.render):
+        (raytraceScene.floorShader):
+        (raytraceScene):
+        (arrayToCanvasCommands):
+        * js/regress/script-tests/v8-raytrace-with-empty-try-catch.js: Added.
+        (Class.create):
+        (Object.extend):
+        (Flog.RayTracer.Color.prototype.initialize):
+        (Flog.RayTracer.Color.prototype.add):
+        (Flog.RayTracer.Color.prototype.addScalar):
+        (Flog.RayTracer.Color.prototype.subtract):
+        (Flog.RayTracer.Color.prototype.multiply):
+        (Flog.RayTracer.Color.prototype.multiplyScalar):
+        (Flog.RayTracer.Color.prototype.divideFactor):
+        (Flog.RayTracer.Color.prototype.limit):
+        (Flog.RayTracer.Color.prototype.distance):
+        (Flog.RayTracer.Color.prototype.blend):
+        (Flog.RayTracer.Color.prototype.brightness):
+        (Flog.RayTracer.Color.prototype.toString):
+        (Flog.RayTracer.Light.prototype.initialize):
+        (Flog.RayTracer.Light.prototype.toString):
+        (Flog.RayTracer.Vector.prototype.initialize):
+        (Flog.RayTracer.Vector.prototype.copy):
+        (Flog.RayTracer.Vector.prototype.normalize):
+        (Flog.RayTracer.Vector.prototype.magnitude):
+        (Flog.RayTracer.Vector.prototype.cross):
+        (Flog.RayTracer.Vector.prototype.dot):
+        (Flog.RayTracer.Vector.prototype.add):
+        (Flog.RayTracer.Vector.prototype.subtract):
+        (Flog.RayTracer.Vector.prototype.multiplyVector):
+        (Flog.RayTracer.Vector.prototype.multiplyScalar):
+        (Flog.RayTracer.Vector.prototype.toString):
+        (Flog.RayTracer.Ray.prototype.initialize):
+        (Flog.RayTracer.Ray.prototype.toString):
+        (Flog.RayTracer.Scene.prototype.initialize):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.initialize):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.getColor):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.wrapUp):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.toString):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
+        (Flog.RayTracer.Shape.Sphere.prototype.initialize):
+        (Flog.RayTracer.Shape.Sphere.prototype.intersect):
+        (Flog.RayTracer.Shape.Sphere.prototype.toString):
+        (Flog.RayTracer.Shape.Plane.prototype.initialize):
+        (Flog.RayTracer.Shape.Plane.prototype.intersect):
+        (Flog.RayTracer.Shape.Plane.prototype.toString):
+        (Flog.RayTracer.IntersectionInfo.prototype.initialize):
+        (Flog.RayTracer.IntersectionInfo.prototype.toString):
+        (Flog.RayTracer.Camera.prototype.initialize):
+        (Flog.RayTracer.Camera.prototype.getRay):
+        (Flog.RayTracer.Camera.prototype.toString):
+        (Flog.RayTracer.Background.prototype.initialize):
+        (Flog.RayTracer.Engine.prototype.initialize):
+        (Flog.RayTracer.Engine.prototype.setPixel):
+        (Flog.RayTracer.Engine.prototype.renderScene):
+        (Flog.RayTracer.Engine.prototype.getPixelColor):
+        (Flog.RayTracer.Engine.prototype.testIntersection):
+        (Flog.RayTracer.Engine.prototype.getReflectionRay):
+        (Flog.RayTracer.Engine.prototype.rayTrace):
+        (renderScene):
+        * js/regress/script-tests/v8-raytrace-with-try-catch.js: Added.
+        (randomException):
+        (Class.create):
+        (Object.extend):
+        (Flog.RayTracer.Color.prototype.initialize):
+        (Flog.RayTracer.Color.prototype.add):
+        (Flog.RayTracer.Color.prototype.addScalar):
+        (Flog.RayTracer.Color.prototype.subtract):
+        (Flog.RayTracer.Color.prototype.multiply):
+        (Flog.RayTracer.Color.prototype.multiplyScalar):
+        (Flog.RayTracer.Color.prototype.divideFactor):
+        (Flog.RayTracer.Color.prototype.limit):
+        (Flog.RayTracer.Color.prototype.distance):
+        (Flog.RayTracer.Color.prototype.blend):
+        (Flog.RayTracer.Color.prototype.brightness):
+        (Flog.RayTracer.Color.prototype.toString):
+        (Flog.RayTracer.Light.prototype.initialize):
+        (Flog.RayTracer.Light.prototype.toString):
+        (Flog.RayTracer.Vector.prototype.initialize):
+        (Flog.RayTracer.Vector.prototype.copy):
+        (Flog.RayTracer.Vector.prototype.normalize):
+        (Flog.RayTracer.Vector.prototype.magnitude):
+        (Flog.RayTracer.Vector.prototype.cross):
+        (Flog.RayTracer.Vector.prototype.dot):
+        (Flog.RayTracer.Vector.prototype.add):
+        (Flog.RayTracer.Vector.prototype.subtract):
+        (Flog.RayTracer.Vector.prototype.multiplyVector):
+        (Flog.RayTracer.Vector.prototype.multiplyScalar):
+        (Flog.RayTracer.Vector.prototype.toString):
+        (Flog.RayTracer.Ray.prototype.initialize):
+        (Flog.RayTracer.Ray.prototype.toString):
+        (Flog.RayTracer.Scene.prototype.initialize):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.initialize):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.getColor):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.wrapUp):
+        (Flog.RayTracer.Material.BaseMaterial.prototype.toString):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
+        (Flog.RayTracer.Material.Solid.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.initialize):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.getColor):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial.toString):
+        (Flog.RayTracer.Material.Chessboard.prototype.Object.extend.new.Flog.RayTracer.Material.BaseMaterial):
+        (Flog.RayTracer.Shape.Sphere.prototype.initialize):
+        (Flog.RayTracer.Shape.Sphere.prototype.intersect):
+        (Flog.RayTracer.Shape.Sphere.prototype.toString):
+        (Flog.RayTracer.Shape.Plane.prototype.initialize):
+        (Flog.RayTracer.Shape.Plane.prototype.intersect):
+        (Flog.RayTracer.Shape.Plane.prototype.toString):
+        (Flog.RayTracer.IntersectionInfo.prototype.initialize):
+        (Flog.RayTracer.IntersectionInfo.prototype.toString):
+        (Flog.RayTracer.Camera.prototype.initialize):
+        (Flog.RayTracer.Camera.prototype.getRay):
+        (Flog.RayTracer.Camera.prototype.toString):
+        (Flog.RayTracer.Background.prototype.initialize):
+        (Flog.RayTracer.Engine.prototype.initialize):
+        (Flog.RayTracer.Engine.prototype.setPixel):
+        (Flog.RayTracer.Engine.prototype.renderScene):
+        (Flog.RayTracer.Engine.prototype.getPixelColor):
+        (Flog.RayTracer.Engine.prototype.testIntersection):
+        (Flog.RayTracer.Engine.prototype.getReflectionRay):
+        (Flog.RayTracer.Engine.prototype.rayTrace):
+        (renderScene):
+        * js/regress/v8-raytrace-with-empty-try-catch-expected.txt: Added.
+        * js/regress/v8-raytrace-with-empty-try-catch.html: Added.
+        * js/regress/v8-raytrace-with-try-catch-expected.txt: Added.
+        * js/regress/v8-raytrace-with-try-catch.html: Added.
+
</ins><span class="cx"> 2015-09-17  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Skip a media test that fails when an AppleTV is around.
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressraytracewithemptytrycatchexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch-expected.txt (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch-expected.txt        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/raytrace-with-empty-try-catch
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressraytracewithemptytrycatchhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch.html (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/raytrace-with-empty-try-catch.html        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/raytrace-with-empty-try-catch.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressraytracewithtrycatchexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/raytrace-with-try-catch-expected.txt (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/raytrace-with-try-catch-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/raytrace-with-try-catch-expected.txt        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/raytrace-with-try-catch
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressraytracewithtrycatchhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/raytrace-with-try-catch.html (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/raytrace-with-try-catch.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/raytrace-with-try-catch.html        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/raytrace-with-try-catch.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsraytracewithemptytrycatchjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/raytrace-with-empty-try-catch.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/raytrace-with-empty-try-catch.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/raytrace-with-empty-try-catch.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,528 @@
</span><ins>+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+
+function createVector(x,y,z) {
+    try {
+        return new Array(x,y,z);
+    } catch(e) { }
+}
+
+function sqrLengthVector(self) {
+    try {
+        return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
+    } catch(e) { }
+}
+
+function lengthVector(self) {
+    try {
+        return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
+    } catch(e) { }
+}
+
+function addVector(self, v) {
+    try {
+        self[0] += v[0];
+        self[1] += v[1];
+    } catch(e) { }
+
+    self[2] += v[2];
+    return self;
+}
+
+function subVector(self, v) {
+    try {
+        self[0] -= v[0];
+        self[1] -= v[1];
+    } catch(e) { 
+    }
+    self[2] -= v[2];
+    return self;
+}
+
+function scaleVector(self, scale) {
+    try {
+        self[0] *= scale;
+        self[1] *= scale;
+    } catch(e) { }
+    self[2] *= scale;
+    return self;
+}
+
+function normaliseVector(self) {
+    var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
+    try {
+        self[0] /= len;
+        self[1] /= len;
+    } catch(e) { }
+    self[2] /= len;
+    return self;
+}
+
+function add(v1, v2) {
+    try {
+        return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
+    } catch(e) { }
+}
+
+function sub(v1, v2) {
+    try {
+        return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
+    } catch(e) { }
+}
+
+function scalev(v1, v2) {
+    try {
+        return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
+    } catch(e) { }
+}
+
+function dot(v1, v2) {
+    try {
+        return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+    } catch(e) { }
+}
+
+function scale(v, scale) {
+    try {
+        return [v[0] * scale, v[1] * scale, v[2] * scale];
+    } catch(e) { }
+}
+
+function cross(v1, v2) {
+    try {
+        return [v1[1] * v2[2] - v1[2] * v2[1], 
+                v1[2] * v2[0] - v1[0] * v2[2],
+                v1[0] * v2[1] - v1[1] * v2[0]];
+    } catch(e) { }
+
+}
+
+function normalise(v) {
+    var len = lengthVector(v);
+    try {
+    } catch(e) { }
+    return [v[0] / len, v[1] / len, v[2] / len];
+}
+
+function transformMatrix(self, v) {
+    try {
+        var vals = self;
+        var x  = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
+        var y  = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
+    } catch(e) { }
+    var z  = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
+    return [x, y, z];
+}
+
+function invertMatrix(self) {
+    try {
+        var temp = new Array(16);
+        var tx = -self[3];
+        var ty = -self[7];
+        var tz = -self[11];
+        for (h = 0; h &lt; 3; h++) 
+            for (v = 0; v &lt; 3; v++) 
+                temp[h + v * 4] = self[v + h * 4];
+    } catch(e) { }
+    try {
+        for (i = 0; i &lt; 11; i++)
+            self[i] = temp[i];
+        self[3] = tx * self[0] + ty * self[1] + tz * self[2];
+        self[7] = tx * self[4] + ty * self[5] + tz * self[6];
+        self[11] = tx * self[8] + ty * self[9] + tz * self[10];
+    } catch(e) { }
+    return self;
+}
+
+
+// Triangle intersection using barycentric coord method
+function Triangle(p1, p2, p3) {
+    try {
+        var edge1 = sub(p3, p1);
+        var edge2 = sub(p2, p1);
+        var normal = cross(edge1, edge2);
+        if (Math.abs(normal[0]) &gt; Math.abs(normal[1]))
+            if (Math.abs(normal[0]) &gt; Math.abs(normal[2]))
+                this.axis = 0; 
+            else 
+                this.axis = 2;
+        else
+            if (Math.abs(normal[1]) &gt; Math.abs(normal[2])) 
+                this.axis = 1;
+            else 
+                this.axis = 2;
+        var u = (this.axis + 1) % 3;
+        var v = (this.axis + 2) % 3;
+        var u1 = edge1[u];
+        var v1 = edge1[v];
+        
+        var u2 = edge2[u];
+        var v2 = edge2[v];
+        this.normal = normalise(normal);
+        this.nu = normal[u] / normal[this.axis];
+        this.nv = normal[v] / normal[this.axis];
+        this.nd = dot(normal, p1) / normal[this.axis];
+        var det = u1 * v2 - v1 * u2;
+        this.eu = p1[u];
+        this.ev = p1[v]; 
+        this.nu1 = u1 / det;
+        this.nv1 = -v1 / det;
+        this.nu2 = v2 / det;
+        this.nv2 = -u2 / det; 
+        this.material = [0.7, 0.7, 0.7];
+    } catch(e) { }
+}
+
+Triangle.prototype.intersect = function(orig, dir, near, far) {
+    try {
+        var u = (this.axis + 1) % 3;
+        var v = (this.axis + 2) % 3;
+        var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
+        var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d;
+    } catch(e) { }
+    if (t &lt; near || t &gt; far)
+        return null;
+    try {
+        var Pu = orig[u] + t * dir[u] - this.eu;
+        var Pv = orig[v] + t * dir[v] - this.ev;
+        var a2 = Pv * this.nu1 + Pu * this.nv1;
+    } catch(e) { }
+    if (a2 &lt; 0) 
+        return null;
+    try {
+        var a3 = Pu * this.nu2 + Pv * this.nv2;
+    } catch(e) { }
+    if (a3 &lt; 0) 
+        return null;
+
+    if ((a2 + a3) &gt; 1) 
+        return null;
+    return t;
+}
+
+function Scene(a_triangles) {
+    try {
+        this.triangles = a_triangles;
+        this.lights = [];
+        this.ambient = [0,0,0];
+        this.background = [0.8,0.8,1];
+    } catch(e) { }
+}
+var zero = new Array(0,0,0);
+
+Scene.prototype.intersect = function(origin, dir, near, far) {
+    var closest = null;
+    for (i = 0; i &lt; this.triangles.length; i++) {
+        try {
+            var triangle = this.triangles[i];   
+            var d = triangle.intersect(origin, dir, near, far);
+            if (d == null || d &gt; far || d &lt; near)
+                continue;
+            far = d;
+            closest = triangle;
+        } catch(e) { }
+    }
+    
+    if (!closest)
+        return [this.background[0],this.background[1],this.background[2]];
+        
+    try {
+        var normal = closest.normal;
+        var hit = add(origin, scale(dir, far)); 
+        if (dot(dir, normal) &gt; 0)
+            normal = [-normal[0], -normal[1], -normal[2]];
+        
+        var colour = null;
+        if (closest.shader) {
+            colour = closest.shader(closest, hit, dir);
+        } else {
+            colour = closest.material;
+        }
+    } catch(e) { }
+    
+    // do reflection
+    var reflected = null;
+    if (colour.reflection &gt; 0.001) {
+        try {
+            var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir);
+            reflected = this.intersect(hit, reflection, 0.0001, 1000000);
+        } catch(e) { }
+        if (colour.reflection &gt;= 0.999999)
+            return reflected;
+    }
+    
+    var l = [this.ambient[0], this.ambient[1], this.ambient[2]];
+    for (var i = 0; i &lt; this.lights.length; i++) {
+        try {
+            var light = this.lights[i];
+            var toLight = sub(light, hit);
+            var distance = lengthVector(toLight);
+            scaleVector(toLight, 1.0/distance);
+            distance -= 0.0001;
+            if (this.blocked(hit, toLight, distance))
+                continue;
+            var nl = dot(normal, toLight);
+            if (nl &gt; 0)
+                addVector(l, scale(light.colour, nl));
+        } catch(e) { }
+    }
+    try {
+        l = scalev(l, colour);
+        if (reflected) {
+            l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
+        }
+    } catch(e) { }
+    return l;
+}
+
+Scene.prototype.blocked = function(O, D, far) {
+    var near = 0.0001;
+    var closest = null;
+    for (i = 0; i &lt; this.triangles.length; i++) {
+        try {
+            var triangle = this.triangles[i];   
+            var d = triangle.intersect(O, D, near, far);
+        } catch(e) { }
+        if (d == null || d &gt; far || d &lt; near)
+            continue;
+        return true;
+    }
+    
+    return false;
+}
+
+
+// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where
+// that somewhere is
+function Camera(origin, lookat, up) {
+    try {
+        var zaxis = normaliseVector(subVector(lookat, origin));
+        var xaxis = normaliseVector(cross(up, zaxis));
+        var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis)));
+        var m = new Array(16);
+        m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2];
+        m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2];
+        m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2];
+        invertMatrix(m);
+        m[3] = 0; m[7] = 0; m[11] = 0;
+        this.origin = origin;
+        this.directions = new Array(4);
+        this.directions[0] = normalise([-0.7,  0.7, 1]);
+        this.directions[1] = normalise([ 0.7,  0.7, 1]);
+        this.directions[2] = normalise([ 0.7, -0.7, 1]);
+        this.directions[3] = normalise([-0.7, -0.7, 1]);
+        this.directions[0] = transformMatrix(m, this.directions[0]);
+        this.directions[1] = transformMatrix(m, this.directions[1]);
+        this.directions[2] = transformMatrix(m, this.directions[2]);
+        this.directions[3] = transformMatrix(m, this.directions[3]);
+
+    } catch(e) { }
+}
+
+Camera.prototype.generateRayPair = function(y) {
+    try {
+        rays = new Array(new Object(), new Object());
+        rays[0].origin = this.origin;
+        rays[1].origin = this.origin;
+        rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
+        rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
+    } catch(e) { }
+    return rays;
+}
+
+function renderRows(camera, scene, pixels, width, height, starty, stopy) {
+    for (var y = starty; y &lt; stopy; y++) {
+        var rays = camera.generateRayPair(y / height);
+        for (var x = 0; x &lt; width; x++) {
+            try {
+                var xp = x / width;
+                var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
+                var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
+                var l = scene.intersect(origin, dir);
+                pixels[y][x] = l;
+            } catch(e) { }
+        }
+    }
+}
+
+Camera.prototype.render = function(scene, pixels, width, height) {
+    try {
+        var cam = this;
+        var row = 0;
+        renderRows(cam, scene, pixels, width, height, 0, height);
+    } catch(e) { }
+}
+
+
+
+function raytraceScene()
+{
+    try {
+        var startDate = new Date().getTime();
+        var numTriangles = 2 * 6;
+        var triangles = new Array();//numTriangles);
+        var tfl = createVector(-10,  10, -10);
+        var tfr = createVector( 10,  10, -10);
+        var tbl = createVector(-10,  10,  10);
+        var tbr = createVector( 10,  10,  10);
+        var bfl = createVector(-10, -10, -10);
+        var bfr = createVector( 10, -10, -10);
+        var bbl = createVector(-10, -10,  10);
+        var bbr = createVector( 10, -10,  10);
+        
+        // cube!!!
+        // front
+        var i = 0;
+        
+        triangles[i++] = new Triangle(tfl, tfr, bfr);
+        triangles[i++] = new Triangle(tfl, bfr, bfl);
+        // back
+        triangles[i++] = new Triangle(tbl, tbr, bbr);
+        triangles[i++] = new Triangle(tbl, bbr, bbl);
+        //        triangles[i-1].material = [0.7,0.2,0.2];
+        //            triangles[i-1].material.reflection = 0.8;
+        // left
+        triangles[i++] = new Triangle(tbl, tfl, bbl);
+        //            triangles[i-1].reflection = 0.6;
+        triangles[i++] = new Triangle(tfl, bfl, bbl);
+        //            triangles[i-1].reflection = 0.6;
+        // right
+        triangles[i++] = new Triangle(tbr, tfr, bbr);
+        triangles[i++] = new Triangle(tfr, bfr, bbr);
+        // top
+        triangles[i++] = new Triangle(tbl, tbr, tfr);
+        triangles[i++] = new Triangle(tbl, tfr, tfl);
+        // bottom
+        triangles[i++] = new Triangle(bbl, bbr, bfr);
+        triangles[i++] = new Triangle(bbl, bfr, bfl);
+        
+        //Floor!!!!
+        var green = createVector(0.0, 0.4, 0.0);
+        var grey = createVector(0.4, 0.4, 0.4);
+        grey.reflection = 1.0;
+
+    } catch(e) { }
+    var floorShader = function(tri, pos, view) {
+        try {
+            var x = ((pos[0]/32) % 2 + 2) % 2;
+            var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2;
+        } catch(e) { }
+        try {
+            if (x &lt; 1 != z &lt; 1) {
+                //in the real world we use the fresnel term...
+                //    var angle = 1-dot(view, tri.normal);
+                //   angle *= angle;
+                //  angle *= angle;
+                // angle *= angle;
+                //grey.reflection = angle;
+                return grey;
+            } else 
+                return green;
+        } catch(e) { }
+    }
+    var ffl = createVector(-1000, -30, -1000);
+    var ffr = createVector( 1000, -30, -1000);
+    var fbl = createVector(-1000, -30,  1000);
+    var fbr = createVector( 1000, -30,  1000);
+    triangles[i++] = new Triangle(fbl, fbr, ffr);
+    triangles[i-1].shader = floorShader;
+    triangles[i++] = new Triangle(fbl, ffr, ffl);
+    triangles[i-1].shader = floorShader;
+    
+    var _scene = new Scene(triangles);
+    _scene.lights[0] = createVector(20, 38, -22);
+    _scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
+    _scene.lights[1] = createVector(-23, 40, 17);
+    _scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
+    _scene.lights[2] = createVector(23, 20, 17);
+    _scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
+    _scene.ambient = createVector(0.1, 0.1, 0.1);
+    //  _scene.background = createVector(0.7, 0.7, 1.0);
+    
+    var size = 30;
+    var pixels = new Array();
+    for (var y = 0; y &lt; size; y++) {
+        try {
+            pixels[y] = new Array();
+        } catch(e) { }
+        for (var x = 0; x &lt; size; x++) {
+            try {
+                pixels[y][x] = 0;
+            } catch(e) { }
+        }
+    }
+
+    try {
+        var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
+        _camera.render(_scene, pixels, size, size);
+    } catch(e){}
+
+    return pixels;
+}
+
+function arrayToCanvasCommands(pixels)
+{
+    var s = '&lt;canvas id=&quot;renderCanvas&quot; width=&quot;30px&quot; height=&quot;30px&quot;&gt;&lt;/canvas&gt;&lt;scr' + 'ipt&gt;\nvar pixels = [';
+    var size = 30;
+    for (var y = 0; y &lt; size; y++) {
+        s += &quot;[&quot;;
+        for (var x = 0; x &lt; size; x++) {
+            s += &quot;[&quot; + pixels[y][x] + &quot;],&quot;;
+        }
+        s+= &quot;],&quot;;
+    }
+    s += '];\n    var canvas = document.getElementById(&quot;renderCanvas&quot;).getContext(&quot;2d&quot;);\n\
+\n\
+\n\
+    var size = 30;\n\
+    canvas.fillStyle = &quot;red&quot;;\n\
+    canvas.fillRect(0, 0, size, size);\n\
+    canvas.scale(1, -1);\n\
+    canvas.translate(0, -size);\n\
+\n\
+    if (!canvas.setFillColor)\n\
+        canvas.setFillColor = function(r, g, b, a) {\n\
+            this.fillStyle = &quot;rgb(&quot;+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+&quot;)&quot;;\n\
+    }\n\
+\n\
+for (var y = 0; y &lt; size; y++) {\n\
+  for (var x = 0; x &lt; size; x++) {\n\
+    var l = pixels[y][x];\n\
+    canvas.setFillColor(l[0], l[1], l[2], 1);\n\
+    canvas.fillRect(x, y, 1, 1);\n\
+  }\n\
+}&lt;/scr' + 'ipt&gt;';
+
+    return s;
+}
+
+testOutput = arrayToCanvasCommands(raytraceScene());
+
+var expectedLength = 20970;
+
+if (testOutput.length != expectedLength)
+    throw &quot;Error: bad result: expected length &quot; + expectedLength + &quot; but got &quot; + testOutput.length;
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsraytracewithtrycatchjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/raytrace-with-try-catch.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/raytrace-with-try-catch.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/raytrace-with-try-catch.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,565 @@
</span><ins>+/*
+ * Copyright (C) 2007 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+let __exceptionCounter = 0;
+function randomException() {
+    __exceptionCounter++;
+    if (__exceptionCounter % 500 === 0) {
+        throw new Error(&quot;rando&quot;);
+    }
+}
+noInline(randomException);
+
+
+function createVector(x,y,z) {
+    try {
+        return new Array(x,y,z);
+    } catch(e) { }
+}
+
+function sqrLengthVector(self) {
+    try {
+        return self[0] * self[0] + self[1] * self[1] + self[2] * self[2];
+    } catch(e) { }
+}
+
+function lengthVector(self) {
+    try {
+        return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
+    } catch(e) { }
+}
+
+function addVector(self, v) {
+    try {
+        self[0] += v[0];
+        self[1] += v[1];
+        randomException();
+    } catch(e) { }
+
+    self[2] += v[2];
+    return self;
+}
+
+function subVector(self, v) {
+    try {
+        self[0] -= v[0];
+        self[1] -= v[1];
+        randomException();
+    } catch(e) { 
+    }
+    self[2] -= v[2];
+    return self;
+}
+
+function scaleVector(self, scale) {
+    try {
+        self[0] *= scale;
+        self[1] *= scale;
+        randomException();
+    } catch(e) { }
+    self[2] *= scale;
+    return self;
+}
+
+function normaliseVector(self) {
+    var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]);
+    try {
+        self[0] /= len;
+        self[1] /= len;
+        randomException();
+    } catch(e) { }
+    self[2] /= len;
+    return self;
+}
+
+function add(v1, v2) {
+    try {
+        return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]);
+    } catch(e) { }
+}
+
+function sub(v1, v2) {
+    try {
+        return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]);
+    } catch(e) { }
+}
+
+function scalev(v1, v2) {
+    try {
+        return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]);
+    } catch(e) { }
+}
+
+function dot(v1, v2) {
+    try {
+        return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+    } catch(e) { }
+}
+
+function scale(v, scale) {
+    try {
+        return [v[0] * scale, v[1] * scale, v[2] * scale];
+    } catch(e) { }
+}
+
+function cross(v1, v2) {
+    try {
+        return [v1[1] * v2[2] - v1[2] * v2[1], 
+                v1[2] * v2[0] - v1[0] * v2[2],
+                v1[0] * v2[1] - v1[1] * v2[0]];
+    } catch(e) { }
+
+}
+
+function normalise(v) {
+    var len = lengthVector(v);
+    try {
+        randomException();
+    } catch(e) { }
+    return [v[0] / len, v[1] / len, v[2] / len];
+}
+
+function transformMatrix(self, v) {
+    try {
+        var vals = self;
+        var x  = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3];
+        var y  = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7];
+        randomException();
+    } catch(e) { }
+    var z  = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11];
+    return [x, y, z];
+}
+
+function invertMatrix(self) {
+    try {
+        var temp = new Array(16);
+        var tx = -self[3];
+        var ty = -self[7];
+        var tz = -self[11];
+        for (h = 0; h &lt; 3; h++) 
+            for (v = 0; v &lt; 3; v++) 
+                temp[h + v * 4] = self[v + h * 4];
+        randomException();
+    } catch(e) { }
+    try {
+        for (i = 0; i &lt; 11; i++)
+            self[i] = temp[i];
+        self[3] = tx * self[0] + ty * self[1] + tz * self[2];
+        self[7] = tx * self[4] + ty * self[5] + tz * self[6];
+        self[11] = tx * self[8] + ty * self[9] + tz * self[10];
+        randomException();
+    } catch(e) { }
+    return self;
+}
+
+
+// Triangle intersection using barycentric coord method
+function Triangle(p1, p2, p3) {
+    try {
+        var edge1 = sub(p3, p1);
+        var edge2 = sub(p2, p1);
+        var normal = cross(edge1, edge2);
+        if (Math.abs(normal[0]) &gt; Math.abs(normal[1]))
+            if (Math.abs(normal[0]) &gt; Math.abs(normal[2]))
+                this.axis = 0; 
+            else 
+                this.axis = 2;
+        else
+            if (Math.abs(normal[1]) &gt; Math.abs(normal[2])) 
+                this.axis = 1;
+            else 
+                this.axis = 2;
+        var u = (this.axis + 1) % 3;
+        var v = (this.axis + 2) % 3;
+        var u1 = edge1[u];
+        var v1 = edge1[v];
+        
+        var u2 = edge2[u];
+        var v2 = edge2[v];
+        this.normal = normalise(normal);
+        this.nu = normal[u] / normal[this.axis];
+        this.nv = normal[v] / normal[this.axis];
+        this.nd = dot(normal, p1) / normal[this.axis];
+        var det = u1 * v2 - v1 * u2;
+        this.eu = p1[u];
+        this.ev = p1[v]; 
+        this.nu1 = u1 / det;
+        this.nv1 = -v1 / det;
+        this.nu2 = v2 / det;
+        this.nv2 = -u2 / det; 
+        this.material = [0.7, 0.7, 0.7];
+        randomException();
+    } catch(e) { }
+}
+
+Triangle.prototype.intersect = function(orig, dir, near, far) {
+    try {
+        var u = (this.axis + 1) % 3;
+        var v = (this.axis + 2) % 3;
+        var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v];
+        var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d;
+        randomException();
+    } catch(e) { }
+    if (t &lt; near || t &gt; far)
+        return null;
+    try {
+        var Pu = orig[u] + t * dir[u] - this.eu;
+        var Pv = orig[v] + t * dir[v] - this.ev;
+        var a2 = Pv * this.nu1 + Pu * this.nv1;
+        randomException();
+    } catch(e) { }
+    if (a2 &lt; 0) 
+        return null;
+    try {
+        var a3 = Pu * this.nu2 + Pv * this.nv2;
+        randomException();
+    } catch(e) { }
+    if (a3 &lt; 0) 
+        return null;
+
+    if ((a2 + a3) &gt; 1) 
+        return null;
+    return t;
+}
+
+function Scene(a_triangles) {
+    try {
+        this.triangles = a_triangles;
+        this.lights = [];
+        this.ambient = [0,0,0];
+        this.background = [0.8,0.8,1];
+        randomException();
+    } catch(e) { }
+}
+var zero = new Array(0,0,0);
+
+Scene.prototype.intersect = function(origin, dir, near, far) {
+    var closest = null;
+    for (i = 0; i &lt; this.triangles.length; i++) {
+        try {
+            var triangle = this.triangles[i];   
+            var d = triangle.intersect(origin, dir, near, far);
+            if (d == null || d &gt; far || d &lt; near)
+                continue;
+            far = d;
+            closest = triangle;
+            randomException();
+        } catch(e) { }
+    }
+    
+    if (!closest)
+        return [this.background[0],this.background[1],this.background[2]];
+        
+    try {
+        var normal = closest.normal;
+        var hit = add(origin, scale(dir, far)); 
+        if (dot(dir, normal) &gt; 0)
+            normal = [-normal[0], -normal[1], -normal[2]];
+        
+        var colour = null;
+        if (closest.shader) {
+            colour = closest.shader(closest, hit, dir);
+        } else {
+            colour = closest.material;
+        }
+        randomException();
+    } catch(e) { }
+    
+    // do reflection
+    var reflected = null;
+    if (colour.reflection &gt; 0.001) {
+        try {
+            var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir);
+            reflected = this.intersect(hit, reflection, 0.0001, 1000000);
+            randomException();
+        } catch(e) { }
+        if (colour.reflection &gt;= 0.999999)
+            return reflected;
+    }
+    
+    var l = [this.ambient[0], this.ambient[1], this.ambient[2]];
+    for (var i = 0; i &lt; this.lights.length; i++) {
+        try {
+            var light = this.lights[i];
+            var toLight = sub(light, hit);
+            var distance = lengthVector(toLight);
+            scaleVector(toLight, 1.0/distance);
+            distance -= 0.0001;
+            if (this.blocked(hit, toLight, distance))
+                continue;
+            var nl = dot(normal, toLight);
+            if (nl &gt; 0)
+                addVector(l, scale(light.colour, nl));
+            randomException();
+        } catch(e) { }
+    }
+    try {
+        l = scalev(l, colour);
+        if (reflected) {
+            l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection));
+        }
+        randomException();
+    } catch(e) { }
+    return l;
+}
+
+Scene.prototype.blocked = function(O, D, far) {
+    var near = 0.0001;
+    var closest = null;
+    for (i = 0; i &lt; this.triangles.length; i++) {
+        try {
+            var triangle = this.triangles[i];   
+            var d = triangle.intersect(O, D, near, far);
+            randomException();
+        } catch(e) { }
+        if (d == null || d &gt; far || d &lt; near)
+            continue;
+        return true;
+    }
+    
+    return false;
+}
+
+
+// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where
+// that somewhere is
+function Camera(origin, lookat, up) {
+    try {
+        var zaxis = normaliseVector(subVector(lookat, origin));
+        var xaxis = normaliseVector(cross(up, zaxis));
+        var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis)));
+        var m = new Array(16);
+        m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2];
+        m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2];
+        m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2];
+        invertMatrix(m);
+        m[3] = 0; m[7] = 0; m[11] = 0;
+        this.origin = origin;
+        this.directions = new Array(4);
+        this.directions[0] = normalise([-0.7,  0.7, 1]);
+        this.directions[1] = normalise([ 0.7,  0.7, 1]);
+        this.directions[2] = normalise([ 0.7, -0.7, 1]);
+        this.directions[3] = normalise([-0.7, -0.7, 1]);
+        this.directions[0] = transformMatrix(m, this.directions[0]);
+        this.directions[1] = transformMatrix(m, this.directions[1]);
+        this.directions[2] = transformMatrix(m, this.directions[2]);
+        this.directions[3] = transformMatrix(m, this.directions[3]);
+
+        randomException();
+    } catch(e) { }
+}
+
+Camera.prototype.generateRayPair = function(y) {
+    try {
+        rays = new Array(new Object(), new Object());
+        rays[0].origin = this.origin;
+        rays[1].origin = this.origin;
+        rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y));
+        rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y));
+        randomException();
+    } catch(e) { }
+    return rays;
+}
+
+function renderRows(camera, scene, pixels, width, height, starty, stopy) {
+    for (var y = starty; y &lt; stopy; y++) {
+        var rays = camera.generateRayPair(y / height);
+        for (var x = 0; x &lt; width; x++) {
+            try {
+                var xp = x / width;
+                var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp));
+                var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp)));
+                var l = scene.intersect(origin, dir);
+                pixels[y][x] = l;
+                randomException();
+            } catch(e) { }
+        }
+    }
+}
+
+Camera.prototype.render = function(scene, pixels, width, height) {
+    try {
+        var cam = this;
+        var row = 0;
+        renderRows(cam, scene, pixels, width, height, 0, height);
+        randomException();
+    } catch(e) { }
+}
+
+
+
+function raytraceScene()
+{
+    try {
+        var startDate = new Date().getTime();
+        var numTriangles = 2 * 6;
+        var triangles = new Array();//numTriangles);
+        var tfl = createVector(-10,  10, -10);
+        var tfr = createVector( 10,  10, -10);
+        var tbl = createVector(-10,  10,  10);
+        var tbr = createVector( 10,  10,  10);
+        var bfl = createVector(-10, -10, -10);
+        var bfr = createVector( 10, -10, -10);
+        var bbl = createVector(-10, -10,  10);
+        var bbr = createVector( 10, -10,  10);
+        
+        // cube!!!
+        // front
+        var i = 0;
+        
+        triangles[i++] = new Triangle(tfl, tfr, bfr);
+        triangles[i++] = new Triangle(tfl, bfr, bfl);
+        // back
+        triangles[i++] = new Triangle(tbl, tbr, bbr);
+        triangles[i++] = new Triangle(tbl, bbr, bbl);
+        //        triangles[i-1].material = [0.7,0.2,0.2];
+        //            triangles[i-1].material.reflection = 0.8;
+        // left
+        triangles[i++] = new Triangle(tbl, tfl, bbl);
+        //            triangles[i-1].reflection = 0.6;
+        triangles[i++] = new Triangle(tfl, bfl, bbl);
+        //            triangles[i-1].reflection = 0.6;
+        // right
+        triangles[i++] = new Triangle(tbr, tfr, bbr);
+        triangles[i++] = new Triangle(tfr, bfr, bbr);
+        // top
+        triangles[i++] = new Triangle(tbl, tbr, tfr);
+        triangles[i++] = new Triangle(tbl, tfr, tfl);
+        // bottom
+        triangles[i++] = new Triangle(bbl, bbr, bfr);
+        triangles[i++] = new Triangle(bbl, bfr, bfl);
+        
+        //Floor!!!!
+        var green = createVector(0.0, 0.4, 0.0);
+        var grey = createVector(0.4, 0.4, 0.4);
+        grey.reflection = 1.0;
+
+        randomException();
+    } catch(e) { }
+    var floorShader = function(tri, pos, view) {
+        try {
+            var x = ((pos[0]/32) % 2 + 2) % 2;
+            var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2;
+            randomException();
+        } catch(e) { }
+        try {
+            if (x &lt; 1 != z &lt; 1) {
+                //in the real world we use the fresnel term...
+                //    var angle = 1-dot(view, tri.normal);
+                //   angle *= angle;
+                //  angle *= angle;
+                // angle *= angle;
+                //grey.reflection = angle;
+                return grey;
+            } else 
+                return green;
+        } catch(e) { }
+    }
+    var ffl = createVector(-1000, -30, -1000);
+    var ffr = createVector( 1000, -30, -1000);
+    var fbl = createVector(-1000, -30,  1000);
+    var fbr = createVector( 1000, -30,  1000);
+    triangles[i++] = new Triangle(fbl, fbr, ffr);
+    triangles[i-1].shader = floorShader;
+    triangles[i++] = new Triangle(fbl, ffr, ffl);
+    triangles[i-1].shader = floorShader;
+    
+    var _scene = new Scene(triangles);
+    _scene.lights[0] = createVector(20, 38, -22);
+    _scene.lights[0].colour = createVector(0.7, 0.3, 0.3);
+    _scene.lights[1] = createVector(-23, 40, 17);
+    _scene.lights[1].colour = createVector(0.7, 0.3, 0.3);
+    _scene.lights[2] = createVector(23, 20, 17);
+    _scene.lights[2].colour = createVector(0.7, 0.7, 0.7);
+    _scene.ambient = createVector(0.1, 0.1, 0.1);
+    //  _scene.background = createVector(0.7, 0.7, 1.0);
+    
+    var size = 30;
+    var pixels = new Array();
+    for (var y = 0; y &lt; size; y++) {
+        try {
+            pixels[y] = new Array();
+            randomException();
+        } catch(e) { }
+        for (var x = 0; x &lt; size; x++) {
+            try {
+                pixels[y][x] = 0;
+                randomException();
+            } catch(e) { }
+        }
+    }
+
+    try {
+        var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0));
+        _camera.render(_scene, pixels, size, size);
+        randomException();
+    } catch(e){}
+
+    return pixels;
+}
+
+function arrayToCanvasCommands(pixels)
+{
+    var s = '&lt;canvas id=&quot;renderCanvas&quot; width=&quot;30px&quot; height=&quot;30px&quot;&gt;&lt;/canvas&gt;&lt;scr' + 'ipt&gt;\nvar pixels = [';
+    var size = 30;
+    for (var y = 0; y &lt; size; y++) {
+        s += &quot;[&quot;;
+        for (var x = 0; x &lt; size; x++) {
+            s += &quot;[&quot; + pixels[y][x] + &quot;],&quot;;
+        }
+        s+= &quot;],&quot;;
+    }
+    s += '];\n    var canvas = document.getElementById(&quot;renderCanvas&quot;).getContext(&quot;2d&quot;);\n\
+\n\
+\n\
+    var size = 30;\n\
+    canvas.fillStyle = &quot;red&quot;;\n\
+    canvas.fillRect(0, 0, size, size);\n\
+    canvas.scale(1, -1);\n\
+    canvas.translate(0, -size);\n\
+\n\
+    if (!canvas.setFillColor)\n\
+        canvas.setFillColor = function(r, g, b, a) {\n\
+            this.fillStyle = &quot;rgb(&quot;+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+&quot;)&quot;;\n\
+    }\n\
+\n\
+for (var y = 0; y &lt; size; y++) {\n\
+  for (var x = 0; x &lt; size; x++) {\n\
+    var l = pixels[y][x];\n\
+    canvas.setFillColor(l[0], l[1], l[2], 1);\n\
+    canvas.fillRect(x, y, 1, 1);\n\
+  }\n\
+}&lt;/scr' + 'ipt&gt;';
+
+    return s;
+}
+
+testOutput = arrayToCanvasCommands(raytraceScene());
+
+var expectedLength = 20970;
+
+if (testOutput.length != expectedLength)
+    throw &quot;Error: bad result: expected length &quot; + expectedLength + &quot; but got &quot; + testOutput.length;
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsv8raytracewithemptytrycatchjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-empty-try-catch.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-empty-try-catch.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-empty-try-catch.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,1048 @@
</span><ins>+// The ray tracer code in this file is written by Adam Burmister. It
+// is available in its original form from:
+//
+//   http://labs.flog.nz.co/raytracer/
+//
+// It has been modified slightly by Google to work as a standalone
+// benchmark, but the all the computational code remains
+// untouched. This file also contains a copy of parts of the Prototype
+// JavaScript framework which is used by the ray tracer.
+
+// Variable used to hold a number that can be used to verify that
+// the scene was ray traced correctly.
+var checkNumber;
+
+
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+// The following is a copy of parts of the Prototype JavaScript library:
+
+// Prototype JavaScript framework, version 1.5.0
+// (c) 2005-2007 Sam Stephenson
+//
+// Prototype is freely distributable under the terms of an MIT-style license.
+// For details, see the Prototype web site: http://prototype.conio.net/
+
+var Class = {
+    create: function() {
+        return function() {
+            try {
+                this.initialize.apply(this, arguments);
+            } catch(e) { }
+        }
+    }
+};
+
+
+Object.extend = function(destination, source) {
+    for (var property in source) {
+        try {
+            destination[property] = source[property];
+        } catch(e) { }
+    }
+    return destination;
+};
+
+
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+// The rest of this file is the actual ray tracer written by Adam
+// Burmister. It's a concatenation of the following files:
+//
+//   flog/color.js
+//   flog/light.js
+//   flog/vector.js
+//   flog/ray.js
+//   flog/scene.js
+//   flog/material/basematerial.js
+//   flog/material/solid.js
+//   flog/material/chessboard.js
+//   flog/shape/baseshape.js
+//   flog/shape/sphere.js
+//   flog/shape/plane.js
+//   flog/intersectioninfo.js
+//   flog/camera.js
+//   flog/background.js
+//   flog/engine.js
+
+
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Color = Class.create();
+
+Flog.RayTracer.Color.prototype = {
+    red : 0.0,
+    green : 0.0,
+    blue : 0.0,
+
+    initialize : function(r, g, b) {
+        try {
+            if(!r) r = 0.0;
+            if(!g) g = 0.0;
+            if(!b) b = 0.0;
+
+            this.red = r;
+            this.green = g;
+            this.blue = b;
+        } catch(e) { }
+    },
+
+    add : function(c1, c2){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red + c2.red;
+            result.green = c1.green + c2.green;
+            result.blue = c1.blue + c2.blue;
+
+        } catch(e) { }
+
+        return result;
+    },
+
+    addScalar: function(c1, s){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red + s;
+            result.green = c1.green + s;
+            result.blue = c1.blue + s;
+
+            result.limit();
+
+        } catch(e) { }
+
+        return result;
+    },
+
+    subtract: function(c1, c2){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red - c2.red;
+            result.green = c1.green - c2.green;
+            result.blue = c1.blue - c2.blue;
+
+        } catch(e) { }
+
+        return result;
+    },
+
+    multiply : function(c1, c2) {
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red * c2.red;
+            result.green = c1.green * c2.green;
+            result.blue = c1.blue * c2.blue;
+
+        } catch(e) { }
+
+        return result;
+    },
+
+    multiplyScalar : function(c1, f) {
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red * f;
+            result.green = c1.green * f;
+            result.blue = c1.blue * f;
+
+        } catch(e) { }
+
+        return result;
+    },
+
+    divideFactor : function(c1, f) {
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red / f;
+            result.green = c1.green / f;
+            result.blue = c1.blue / f;
+
+        } catch(e) { }
+
+        return result;
+    },
+
+    limit: function(){
+        try { 
+            this.red = (this.red &gt; 0.0) ? ( (this.red &gt; 1.0) ? 1.0 : this.red ) : 0.0;
+            this.green = (this.green &gt; 0.0) ? ( (this.green &gt; 1.0) ? 1.0 : this.green ) : 0.0;
+            this.blue = (this.blue &gt; 0.0) ? ( (this.blue &gt; 1.0) ? 1.0 : this.blue ) : 0.0;
+
+        } catch(e) { }
+    },
+
+    distance : function(color) {
+        try {
+            var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue);
+        } catch(e) { }
+        return d;
+    },
+
+    blend: function(c1, c2, w){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+            result = Flog.RayTracer.Color.prototype.add(
+                    Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w),
+                    Flog.RayTracer.Color.prototype.multiplyScalar(c2, w)
+                    );
+        } catch(e) { }
+        return result;
+    },
+
+    brightness : function() {
+        try {
+            var r = Math.floor(this.red*255);
+            var g = Math.floor(this.green*255);
+            var b = Math.floor(this.blue*255);
+        } catch(e) { }
+        return (r * 77 + g * 150 + b * 29) &gt;&gt; 8;
+    },
+
+    toString : function () {
+        try {
+            var r = Math.floor(this.red*255);
+            var g = Math.floor(this.green*255);
+            var b = Math.floor(this.blue*255);
+        } catch(e) { }
+
+        return &quot;rgb(&quot;+ r +&quot;,&quot;+ g +&quot;,&quot;+ b +&quot;)&quot;;
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Light = Class.create();
+
+Flog.RayTracer.Light.prototype = {
+    position: null,
+    color: null,
+    intensity: 10.0,
+
+    initialize : function(pos, color, intensity) {
+        try {
+            this.position = pos;
+            this.color = color;
+            this.intensity = (intensity ? intensity : 10.0);
+
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            var result = 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']';
+        } catch(e) { }
+        return result;
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Vector = Class.create();
+
+Flog.RayTracer.Vector.prototype = {
+    x : 0.0,
+    y : 0.0,
+    z : 0.0,
+
+    initialize : function(x, y, z) {
+        try {
+            this.x = (x ? x : 0);
+            this.y = (y ? y : 0);
+            this.z = (z ? z : 0);
+        } catch(e) { }
+    },
+
+    copy: function(vector){
+        try {
+            this.x = vector.x;
+            this.y = vector.y;
+            this.z = vector.z;
+        } catch(e) { }
+    },
+
+    normalize : function() {
+        try {
+            var m = this.magnitude();
+            var result = new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m);
+        } catch(e) { }
+        return result;
+    },
+
+    magnitude : function() {
+        try {
+            return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
+        } catch(e)  { }
+    },
+
+    cross : function(w) {
+        try {
+            return new Flog.RayTracer.Vector(
+                    -this.z * w.y + this.y * w.z,
+                    this.z * w.x - this.x * w.z,
+                    -this.y * w.x + this.x * w.y);
+        } catch(e) { }
+    },
+
+    dot : function(w) {
+        try {
+            return this.x * w.x + this.y * w.y + this.z * w.z;
+        } catch(e) { }
+    },
+
+    add : function(v, w) {
+        try {
+            return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z);
+        } catch(e) { }
+    },
+
+    subtract : function(v, w) {
+        try {
+            if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']';
+            return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z);
+        } catch(e) { }
+    },
+
+    multiplyVector : function(v, w) {
+        try {
+            return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z);
+        } catch(e) { }
+    },
+
+    multiplyScalar : function(v, w) {
+        try {
+            return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w);
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Ray = Class.create();
+
+Flog.RayTracer.Ray.prototype = {
+    position : null,
+    direction : null,
+    initialize : function(pos, dir) {
+        try {
+            this.position = pos;
+            this.direction = dir;
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            return 'Ray [' + this.position + ',' + this.direction + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Scene = Class.create();
+
+Flog.RayTracer.Scene.prototype = {
+    camera : null,
+    shapes : [],
+    lights : [],
+    background : null,
+
+    initialize : function() {
+        try {
+            this.camera = new Flog.RayTracer.Camera(
+                    new Flog.RayTracer.Vector(0,0,-5),
+                    new Flog.RayTracer.Vector(0,0,1),
+                    new Flog.RayTracer.Vector(0,1,0)
+                    );
+            this.shapes = new Array();
+            this.lights = new Array();
+            this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2);
+
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {};
+
+Flog.RayTracer.Material.BaseMaterial = Class.create();
+
+Flog.RayTracer.Material.BaseMaterial.prototype = {
+
+    gloss: 2.0,             // [0...infinity] 0 = matt
+    transparency: 0.0,      // 0=opaque
+    reflection: 0.0,        // [0...infinity] 0 = no reflection
+    refraction: 0.50,
+    hasTexture: false,
+
+    initialize : function() {
+
+    },
+
+    getColor: function(u, v){
+
+    },
+
+    wrapUp: function(t){
+        try {
+            t = t % 2.0;
+            if(t &lt; -1) t += 2.0;
+            if(t &gt;= 1) t -= 2.0;
+        } catch(e) { }
+        return t;
+    },
+
+    toString : function () {
+        try {
+            return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Material.Solid = Class.create();
+
+Flog.RayTracer.Material.Solid.prototype = Object.extend(
+        new Flog.RayTracer.Material.BaseMaterial(), {
+            initialize : function(color, reflection, refraction, transparency, gloss) {
+                try {
+                    this.color = color;
+                    this.reflection = reflection;
+                    this.transparency = transparency;
+                    this.gloss = gloss;
+                    this.hasTexture = false;
+                } catch(e) { }
+            },
+
+            getColor: function(u, v){
+                try {
+                    return this.color;
+                } catch(e) { }
+            },
+
+            toString : function () {
+                try {
+                    return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+                } catch(e) { }
+            }
+        }
+        );
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Material.Chessboard = Class.create();
+
+Flog.RayTracer.Material.Chessboard.prototype = Object.extend(
+        new Flog.RayTracer.Material.BaseMaterial(), {
+            colorEven: null,
+            colorOdd: null,
+            density: 0.5,
+
+            initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) {
+                try {
+                    this.colorEven = colorEven;
+                    this.colorOdd = colorOdd;
+                    this.reflection = reflection;
+                    this.transparency = transparency;
+                    this.gloss = gloss;
+                    this.density = density;
+                    this.hasTexture = true;
+                } catch(e) { }
+            },
+
+            getColor: function(u, v){
+                try {
+                    var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
+                } catch(e) { }
+
+                if(t &lt; 0.0)
+                    return this.colorEven;
+                else
+                    return this.colorOdd;
+            },
+
+            toString : function () {
+                try {
+                    return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+                } catch(e) { }
+            }
+        }
+);
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.Sphere = Class.create();
+
+Flog.RayTracer.Shape.Sphere.prototype = {
+    initialize : function(pos, radius, material) {
+        try {
+            this.radius = radius;
+            this.position = pos;
+            this.material = material;
+
+        } catch(e) { }
+    },
+
+    intersect: function(ray){
+        try {
+            var info = new Flog.RayTracer.IntersectionInfo();
+            info.shape = this;
+
+            var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position);
+
+            var B = dst.dot(ray.direction);
+            var C = dst.dot(dst) - (this.radius * this.radius);
+            var D = (B * B) - C;
+
+            if(D &gt; 0){ // intersection!
+                info.isHit = true;
+                info.distance = (-B) - Math.sqrt(D);
+                info.position = Flog.RayTracer.Vector.prototype.add(
+                        ray.position,
+                        Flog.RayTracer.Vector.prototype.multiplyScalar(
+                            ray.direction,
+                            info.distance
+                            )
+                        );
+                info.normal = Flog.RayTracer.Vector.prototype.subtract(
+                        info.position,
+                        this.position
+                        ).normalize();
+
+                info.color = this.material.getColor(0,0);
+            } else {
+                info.isHit = false;
+            }
+
+        } catch(e) { }
+        return info;
+    },
+
+    toString : function () {
+        try {
+            return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.Plane = Class.create();
+
+Flog.RayTracer.Shape.Plane.prototype = {
+    d: 0.0,
+
+    initialize : function(pos, d, material) {
+        try {
+            this.position = pos;
+            this.d = d;
+            this.material = material;
+        } catch(e) { }
+    },
+
+    intersect: function(ray){
+        try {
+            var info = new Flog.RayTracer.IntersectionInfo();
+
+            var Vd = this.position.dot(ray.direction);
+            if(Vd == 0) return info; // no intersection
+
+            var t = -(this.position.dot(ray.position) + this.d) / Vd;
+            if(t &lt;= 0) return info;
+
+            info.shape = this;
+            info.isHit = true;
+            info.position = Flog.RayTracer.Vector.prototype.add(
+                    ray.position,
+                    Flog.RayTracer.Vector.prototype.multiplyScalar(
+                        ray.direction,
+                        t
+                        )
+                    );
+            info.normal = this.position;
+            info.distance = t;
+
+            if(this.material.hasTexture){
+                var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x);
+                var vV = vU.cross(this.position);
+                var u = info.position.dot(vU);
+                var v = info.position.dot(vV);
+                info.color = this.material.getColor(u,v);
+            } else {
+                info.color = this.material.getColor(0,0);
+            }
+
+        } catch(e) { }
+        return info;
+    },
+
+    toString : function () {
+        try {
+            return 'Plane [' + this.position + ', d=' + this.d + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.IntersectionInfo = Class.create();
+
+Flog.RayTracer.IntersectionInfo.prototype = {
+    isHit: false,
+    hitCount: 0,
+    shape: null,
+    position: null,
+    normal: null,
+    color: null,
+    distance: null,
+
+    initialize : function() {
+        try {
+            this.color = new Flog.RayTracer.Color(0,0,0);
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            return 'Intersection [' + this.position + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Camera = Class.create();
+
+Flog.RayTracer.Camera.prototype = {
+    position: null,
+    lookAt: null,
+    equator: null,
+    up: null,
+    screen: null,
+
+    initialize : function(pos, lookAt, up) {
+        try {
+            this.position = pos;
+            this.lookAt = lookAt;
+            this.up = up;
+            this.equator = lookAt.normalize().cross(this.up);
+            this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt);
+        } catch(e) { }
+    },
+
+    getRay: function(vx, vy){
+        try {
+            var pos = Flog.RayTracer.Vector.prototype.subtract(
+                    this.screen,
+                    Flog.RayTracer.Vector.prototype.subtract(
+                        Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx),
+                        Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy)
+                        )
+                    );
+            pos.y = pos.y * -1;
+            var dir = Flog.RayTracer.Vector.prototype.subtract(
+                    pos,
+                    this.position
+                    );
+
+            var ray = new Flog.RayTracer.Ray(pos, dir.normalize());
+
+        } catch(e) { }
+        return ray;
+    },
+
+    toString : function () {
+        try {
+            return 'Ray []';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Background = Class.create();
+
+Flog.RayTracer.Background.prototype = {
+    color : null,
+    ambience : 0.0,
+
+    initialize : function(color, ambience) {
+        try {
+            this.color = color;
+            this.ambience = ambience;
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Engine = Class.create();
+
+Flog.RayTracer.Engine.prototype = {
+    canvas: null, /* 2d context we can render to */
+
+    initialize: function(options){
+        try {
+            this.options = Object.extend({
+                canvasHeight: 100,
+                canvasWidth: 100,
+                pixelWidth: 2,
+                pixelHeight: 2,
+                renderDiffuse: false,
+                renderShadows: false,
+                renderHighlights: false,
+                renderReflections: false,
+                rayDepth: 2
+            }, options || {});
+
+            this.options.canvasHeight /= this.options.pixelHeight;
+            this.options.canvasWidth /= this.options.pixelWidth;
+
+        } catch(e) { }
+
+        /* TODO: dynamically include other scripts */
+    },
+
+    setPixel: function(x, y, color){
+        try {
+            var pxW, pxH;
+            pxW = this.options.pixelWidth;
+            pxH = this.options.pixelHeight;
+
+            if (this.canvas) {
+                this.canvas.fillStyle = color.toString();
+                this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
+            } else {
+                if (x ===  y) {
+                    checkNumber += color.brightness();
+                }
+                // print(x * pxW, y * pxH, pxW, pxH);
+            }
+
+        } catch(e) { }
+    },
+
+    renderScene: function(scene, canvas){
+        try {
+            checkNumber = 0;
+            /* Get canvas */
+            if (canvas) {
+                this.canvas = canvas.getContext(&quot;2d&quot;);
+            } else {
+                this.canvas = null;
+            }
+
+            var canvasHeight = this.options.canvasHeight;
+            var canvasWidth = this.options.canvasWidth;
+
+            for(var y=0; y &lt; canvasHeight; y++){
+                for(var x=0; x &lt; canvasWidth; x++){
+                    try {
+                        var yp = y * 1.0 / canvasHeight * 2 - 1;
+                        var xp = x * 1.0 / canvasWidth * 2 - 1;
+
+                        var ray = scene.camera.getRay(xp, yp);
+
+                        var color = this.getPixelColor(ray, scene);
+
+                        this.setPixel(x, y, color);
+
+                    } catch(e) { }
+                }
+            }
+        } catch(e) { }
+        if (checkNumber !== 2321) {
+            throw new Error(&quot;Scene rendered incorrectly&quot;);
+        }
+    },
+
+    getPixelColor: function(ray, scene){
+        try {
+            var info = this.testIntersection(ray, scene, null);
+            if(info.isHit){
+                var color = this.rayTrace(info, ray, scene, 0);
+                return color;
+            }
+            return scene.background.color;
+        } catch(e) { }
+    },
+
+    testIntersection: function(ray, scene, exclude){
+        try {
+            var hits = 0;
+            var best = new Flog.RayTracer.IntersectionInfo();
+            best.distance = 2000;
+
+            for(var i=0; i&lt;scene.shapes.length; i++){
+                try {
+                    var shape = scene.shapes[i];
+
+                    if(shape != exclude){
+                        var info = shape.intersect(ray);
+                        if(info.isHit &amp;&amp; info.distance &gt;= 0 &amp;&amp; info.distance &lt; best.distance){
+                            best = info;
+                            hits++;
+                        }
+                    }
+
+                } catch(e) { }
+            }
+            best.hitCount = hits;
+
+        } catch(e) { }
+        return best;
+    },
+
+    getReflectionRay: function(P,N,V){
+        try {
+            var c1 = -N.dot(V);
+            var R1 = Flog.RayTracer.Vector.prototype.add(
+                    Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1),
+                    V
+                    );
+
+        } catch(e) { }
+        return new Flog.RayTracer.Ray(P, R1);
+    },
+
+    rayTrace: function(info, ray, scene, depth){
+        // Calc ambient
+        try {
+            var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience);
+            var oldColor = color;
+            var shininess = Math.pow(10, info.shape.material.gloss + 1);
+
+            for(var i=0; i&lt;scene.lights.length; i++){
+                try {
+                    var light = scene.lights[i];
+
+                    // Calc diffuse lighting
+                    var v = Flog.RayTracer.Vector.prototype.subtract(
+                            light.position,
+                            info.position
+                            ).normalize();
+
+                    if(this.options.renderDiffuse){
+                        var L = v.dot(info.normal);
+                        if(L &gt; 0.0){
+                            color = Flog.RayTracer.Color.prototype.add(
+                                    color,
+                                    Flog.RayTracer.Color.prototype.multiply(
+                                        info.color,
+                                        Flog.RayTracer.Color.prototype.multiplyScalar(
+                                            light.color,
+                                            L
+                                            )
+                                        )
+                                    );
+                        }
+                    }
+
+                } catch(e) { }
+
+                try {
+                    // The greater the depth the more accurate the colours, but
+                    // this is exponentially (!) expensive
+                    if(depth &lt;= this.options.rayDepth){
+                        // calculate reflection ray
+                        if(this.options.renderReflections &amp;&amp; info.shape.material.reflection &gt; 0)
+                        {
+                            var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
+                            var refl = this.testIntersection(reflectionRay, scene, info.shape);
+
+                            if (refl.isHit &amp;&amp; refl.distance &gt; 0){
+                                refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
+                            } else {
+                                refl.color = scene.background.color;
+                            }
+
+                            color = Flog.RayTracer.Color.prototype.blend(
+                                    color,
+                                    refl.color,
+                                    info.shape.material.reflection
+                                    );
+                        }
+
+                        // Refraction
+                        /* TODO */
+                    }
+                }  catch(e) { }
+
+                /* Render shadows and highlights */
+
+                var shadowInfo = new Flog.RayTracer.IntersectionInfo();
+
+                if(this.options.renderShadows){
+                    var shadowRay = new Flog.RayTracer.Ray(info.position, v);
+
+                    shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
+                    if(shadowInfo.isHit &amp;&amp; shadowInfo.shape != info.shape /*&amp;&amp; shadowInfo.shape.type != 'PLANE'*/){
+                        var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5);
+                        var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5));
+                        color = Flog.RayTracer.Color.prototype.addScalar(vA,dB);
+                    }
+                }
+
+                try {
+                    // Phong specular highlights
+                    if(this.options.renderHighlights &amp;&amp; !shadowInfo.isHit &amp;&amp; info.shape.material.gloss &gt; 0){
+                        var Lv = Flog.RayTracer.Vector.prototype.subtract(
+                                info.shape.position,
+                                light.position
+                                ).normalize();
+
+                        var E = Flog.RayTracer.Vector.prototype.subtract(
+                                scene.camera.position,
+                                info.shape.position
+                                ).normalize();
+
+                        var H = Flog.RayTracer.Vector.prototype.subtract(
+                                E,
+                                Lv
+                                ).normalize();
+
+                        var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess);
+                        color = Flog.RayTracer.Color.prototype.add(
+                                Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight),
+                                color
+                                );
+                    }
+                } catch(e) { }
+            }
+            color.limit();
+
+        } catch(e) { }
+        return color;
+    }
+};
+
+
+function renderScene(){
+    try {
+        var scene = new Flog.RayTracer.Scene();
+
+        scene.camera = new Flog.RayTracer.Camera(
+                new Flog.RayTracer.Vector(0, 0, -15),
+                new Flog.RayTracer.Vector(-0.2, 0, 5),
+                new Flog.RayTracer.Vector(0, 1, 0)
+                );
+
+        scene.background = new Flog.RayTracer.Background(
+                new Flog.RayTracer.Color(0.5, 0.5, 0.5),
+                0.4
+                );
+
+        var sphere = new Flog.RayTracer.Shape.Sphere(
+                new Flog.RayTracer.Vector(-1.5, 1.5, 2),
+                1.5,
+                new Flog.RayTracer.Material.Solid(
+                    new Flog.RayTracer.Color(0,0.5,0.5),
+                    0.3,
+                    0.0,
+                    0.0,
+                    2.0
+                    )
+                );
+
+        var sphere1 = new Flog.RayTracer.Shape.Sphere(
+                new Flog.RayTracer.Vector(1, 0.25, 1),
+                0.5,
+                new Flog.RayTracer.Material.Solid(
+                    new Flog.RayTracer.Color(0.9,0.9,0.9),
+                    0.1,
+                    0.0,
+                    0.0,
+                    1.5
+                    )
+                );
+
+        var plane = new Flog.RayTracer.Shape.Plane(
+                new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(),
+                1.2,
+                new Flog.RayTracer.Material.Chessboard(
+                    new Flog.RayTracer.Color(1,1,1),
+                    new Flog.RayTracer.Color(0,0,0),
+                    0.2,
+                    0.0,
+                    1.0,
+                    0.7
+                    )
+                );
+
+        scene.shapes.push(plane);
+        scene.shapes.push(sphere);
+        scene.shapes.push(sphere1);
+
+        var light = new Flog.RayTracer.Light(
+                new Flog.RayTracer.Vector(5, 10, -1),
+                new Flog.RayTracer.Color(0.8, 0.8, 0.8)
+                );
+
+        var light1 = new Flog.RayTracer.Light(
+                new Flog.RayTracer.Vector(-3, 5, -15),
+                new Flog.RayTracer.Color(0.8, 0.8, 0.8),
+                100
+                );
+
+        scene.lights.push(light);
+        scene.lights.push(light1);
+
+        var imageWidth = 100; // $F('imageWidth');
+        var imageHeight = 100; // $F('imageHeight');
+        var pixelSize = &quot;5,5&quot;.split(','); //  $F('pixelSize').split(',');
+        var renderDiffuse = true; // $F('renderDiffuse');
+        var renderShadows = true; // $F('renderShadows');
+        var renderHighlights = true; // $F('renderHighlights');
+        var renderReflections = true; // $F('renderReflections');
+        var rayDepth = 2;//$F('rayDepth');
+
+        var raytracer = new Flog.RayTracer.Engine(
+                {
+                    canvasWidth: imageWidth,
+                    canvasHeight: imageHeight,
+                    pixelWidth: pixelSize[0],
+                    pixelHeight: pixelSize[1],
+                    &quot;renderDiffuse&quot;: renderDiffuse,
+                    &quot;renderHighlights&quot;: renderHighlights,
+                    &quot;renderShadows&quot;: renderShadows,
+                    &quot;renderReflections&quot;: renderReflections,
+                    &quot;rayDepth&quot;: rayDepth
+                }
+                );
+
+        raytracer.renderScene(scene, null, 0);
+    } catch(e) { }
+}
+
+for (var i = 0; i &lt; 6; ++i)
+    renderScene();
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsv8raytracewithtrycatchjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-try-catch.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-try-catch.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/v8-raytrace-with-try-catch.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,1101 @@
</span><ins>+// The ray tracer code in this file is written by Adam Burmister. It
+// is available in its original form from:
+//
+//   http://labs.flog.nz.co/raytracer/
+//
+// It has been modified slightly by Google to work as a standalone
+// benchmark, but the all the computational code remains
+// untouched. This file also contains a copy of parts of the Prototype
+// JavaScript framework which is used by the ray tracer.
+
+// Variable used to hold a number that can be used to verify that
+// the scene was ray traced correctly.
+var checkNumber;
+
+
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+// The following is a copy of parts of the Prototype JavaScript library:
+
+// Prototype JavaScript framework, version 1.5.0
+// (c) 2005-2007 Sam Stephenson
+//
+// Prototype is freely distributable under the terms of an MIT-style license.
+// For details, see the Prototype web site: http://prototype.conio.net/
+
+let __exceptionCounter = 0;
+function randomException() {
+    __exceptionCounter++;
+    if (__exceptionCounter % 500 === 0) {
+        throw new Error(&quot;rando&quot;);
+    }
+}
+noInline(randomException);
+
+var Class = {
+    create: function() {
+        return function() {
+            try {
+                this.initialize.apply(this, arguments);
+                randomException();
+            } catch(e) { }
+        }
+    }
+};
+
+
+Object.extend = function(destination, source) {
+    for (var property in source) {
+        try {
+            destination[property] = source[property];
+            randomException();
+        } catch(e) { }
+    }
+    return destination;
+};
+
+
+// ------------------------------------------------------------------------
+// ------------------------------------------------------------------------
+
+// The rest of this file is the actual ray tracer written by Adam
+// Burmister. It's a concatenation of the following files:
+//
+//   flog/color.js
+//   flog/light.js
+//   flog/vector.js
+//   flog/ray.js
+//   flog/scene.js
+//   flog/material/basematerial.js
+//   flog/material/solid.js
+//   flog/material/chessboard.js
+//   flog/shape/baseshape.js
+//   flog/shape/sphere.js
+//   flog/shape/plane.js
+//   flog/intersectioninfo.js
+//   flog/camera.js
+//   flog/background.js
+//   flog/engine.js
+
+
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Color = Class.create();
+
+Flog.RayTracer.Color.prototype = {
+    red : 0.0,
+    green : 0.0,
+    blue : 0.0,
+
+    initialize : function(r, g, b) {
+        try {
+            if(!r) r = 0.0;
+            if(!g) g = 0.0;
+            if(!b) b = 0.0;
+
+            this.red = r;
+            this.green = g;
+            this.blue = b;
+            randomException();
+        } catch(e) { }
+    },
+
+    add : function(c1, c2){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red + c2.red;
+            result.green = c1.green + c2.green;
+            result.blue = c1.blue + c2.blue;
+
+            randomException();
+        } catch(e) { }
+
+        return result;
+    },
+
+    addScalar: function(c1, s){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red + s;
+            result.green = c1.green + s;
+            result.blue = c1.blue + s;
+
+            result.limit();
+
+            randomException();
+        } catch(e) { }
+
+        return result;
+    },
+
+    subtract: function(c1, c2){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red - c2.red;
+            result.green = c1.green - c2.green;
+            result.blue = c1.blue - c2.blue;
+
+            randomException();
+        } catch(e) { }
+
+        return result;
+    },
+
+    multiply : function(c1, c2) {
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red * c2.red;
+            result.green = c1.green * c2.green;
+            result.blue = c1.blue * c2.blue;
+
+            randomException();
+        } catch(e) { }
+
+        return result;
+    },
+
+    multiplyScalar : function(c1, f) {
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red * f;
+            result.green = c1.green * f;
+            result.blue = c1.blue * f;
+
+            randomException();
+        } catch(e) { }
+
+        return result;
+    },
+
+    divideFactor : function(c1, f) {
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+
+            result.red = c1.red / f;
+            result.green = c1.green / f;
+            result.blue = c1.blue / f;
+
+            randomException();
+        } catch(e) { }
+
+        return result;
+    },
+
+    limit: function(){
+        try { 
+            this.red = (this.red &gt; 0.0) ? ( (this.red &gt; 1.0) ? 1.0 : this.red ) : 0.0;
+            this.green = (this.green &gt; 0.0) ? ( (this.green &gt; 1.0) ? 1.0 : this.green ) : 0.0;
+            this.blue = (this.blue &gt; 0.0) ? ( (this.blue &gt; 1.0) ? 1.0 : this.blue ) : 0.0;
+
+            randomException();
+        } catch(e) { }
+    },
+
+    distance : function(color) {
+        try {
+            var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue);
+            randomException();
+        } catch(e) { }
+        return d;
+    },
+
+    blend: function(c1, c2, w){
+        try {
+            var result = new Flog.RayTracer.Color(0,0,0);
+            result = Flog.RayTracer.Color.prototype.add(
+                    Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w),
+                    Flog.RayTracer.Color.prototype.multiplyScalar(c2, w)
+                    );
+            randomException();
+        } catch(e) { }
+        return result;
+    },
+
+    brightness : function() {
+        try {
+            var r = Math.floor(this.red*255);
+            var g = Math.floor(this.green*255);
+            var b = Math.floor(this.blue*255);
+            randomException();
+        } catch(e) { }
+        return (r * 77 + g * 150 + b * 29) &gt;&gt; 8;
+    },
+
+    toString : function () {
+        try {
+            var r = Math.floor(this.red*255);
+            var g = Math.floor(this.green*255);
+            var b = Math.floor(this.blue*255);
+            randomException();
+        } catch(e) { }
+
+        return &quot;rgb(&quot;+ r +&quot;,&quot;+ g +&quot;,&quot;+ b +&quot;)&quot;;
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Light = Class.create();
+
+Flog.RayTracer.Light.prototype = {
+    position: null,
+    color: null,
+    intensity: 10.0,
+
+    initialize : function(pos, color, intensity) {
+        try {
+            this.position = pos;
+            this.color = color;
+            this.intensity = (intensity ? intensity : 10.0);
+
+            randomException();
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            var result = 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']';
+            randomException();
+        } catch(e) { }
+        return result;
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Vector = Class.create();
+
+Flog.RayTracer.Vector.prototype = {
+    x : 0.0,
+    y : 0.0,
+    z : 0.0,
+
+    initialize : function(x, y, z) {
+        try {
+            this.x = (x ? x : 0);
+            this.y = (y ? y : 0);
+            this.z = (z ? z : 0);
+            randomException();
+        } catch(e) { }
+    },
+
+    copy: function(vector){
+        try {
+            this.x = vector.x;
+            this.y = vector.y;
+            this.z = vector.z;
+            randomException();
+        } catch(e) { }
+    },
+
+    normalize : function() {
+        try {
+            var m = this.magnitude();
+            var result = new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m);
+            randomException();
+        } catch(e) { }
+        return result;
+    },
+
+    magnitude : function() {
+        try {
+            return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
+        } catch(e)  { }
+    },
+
+    cross : function(w) {
+        try {
+            return new Flog.RayTracer.Vector(
+                    -this.z * w.y + this.y * w.z,
+                    this.z * w.x - this.x * w.z,
+                    -this.y * w.x + this.x * w.y);
+        } catch(e) { }
+    },
+
+    dot : function(w) {
+        try {
+            return this.x * w.x + this.y * w.y + this.z * w.z;
+        } catch(e) { }
+    },
+
+    add : function(v, w) {
+        try {
+            return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z);
+        } catch(e) { }
+    },
+
+    subtract : function(v, w) {
+        try {
+            if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']';
+            return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z);
+        } catch(e) { }
+    },
+
+    multiplyVector : function(v, w) {
+        try {
+            return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z);
+        } catch(e) { }
+    },
+
+    multiplyScalar : function(v, w) {
+        try {
+            return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w);
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Ray = Class.create();
+
+Flog.RayTracer.Ray.prototype = {
+    position : null,
+    direction : null,
+    initialize : function(pos, dir) {
+        try {
+            this.position = pos;
+            this.direction = dir;
+            randomException();
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            return 'Ray [' + this.position + ',' + this.direction + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Scene = Class.create();
+
+Flog.RayTracer.Scene.prototype = {
+    camera : null,
+    shapes : [],
+    lights : [],
+    background : null,
+
+    initialize : function() {
+        try {
+            this.camera = new Flog.RayTracer.Camera(
+                    new Flog.RayTracer.Vector(0,0,-5),
+                    new Flog.RayTracer.Vector(0,0,1),
+                    new Flog.RayTracer.Vector(0,1,0)
+                    );
+            this.shapes = new Array();
+            this.lights = new Array();
+            this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2);
+
+            randomException();
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {};
+
+Flog.RayTracer.Material.BaseMaterial = Class.create();
+
+Flog.RayTracer.Material.BaseMaterial.prototype = {
+
+    gloss: 2.0,             // [0...infinity] 0 = matt
+    transparency: 0.0,      // 0=opaque
+    reflection: 0.0,        // [0...infinity] 0 = no reflection
+    refraction: 0.50,
+    hasTexture: false,
+
+    initialize : function() {
+
+    },
+
+    getColor: function(u, v){
+
+    },
+
+    wrapUp: function(t){
+        try {
+            t = t % 2.0;
+            if(t &lt; -1) t += 2.0;
+            if(t &gt;= 1) t -= 2.0;
+            randomException();
+        } catch(e) { }
+        return t;
+    },
+
+    toString : function () {
+        try {
+            return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Material.Solid = Class.create();
+
+Flog.RayTracer.Material.Solid.prototype = Object.extend(
+        new Flog.RayTracer.Material.BaseMaterial(), {
+            initialize : function(color, reflection, refraction, transparency, gloss) {
+                try {
+                    this.color = color;
+                    this.reflection = reflection;
+                    this.transparency = transparency;
+                    this.gloss = gloss;
+                    this.hasTexture = false;
+                    randomException();
+                } catch(e) { }
+            },
+
+            getColor: function(u, v){
+                try {
+                    return this.color;
+                } catch(e) { }
+            },
+
+            toString : function () {
+                try {
+                    return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+                } catch(e) { }
+            }
+        }
+        );
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Material.Chessboard = Class.create();
+
+Flog.RayTracer.Material.Chessboard.prototype = Object.extend(
+        new Flog.RayTracer.Material.BaseMaterial(), {
+            colorEven: null,
+            colorOdd: null,
+            density: 0.5,
+
+            initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) {
+                try {
+                    this.colorEven = colorEven;
+                    this.colorOdd = colorOdd;
+                    this.reflection = reflection;
+                    this.transparency = transparency;
+                    this.gloss = gloss;
+                    this.density = density;
+                    this.hasTexture = true;
+                    randomException();
+                } catch(e) { }
+            },
+
+            getColor: function(u, v){
+                try {
+                    var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
+                    randomException();
+                } catch(e) { }
+
+                if(t &lt; 0.0)
+                    return this.colorEven;
+                else
+                    return this.colorOdd;
+            },
+
+            toString : function () {
+                try {
+                    return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
+                } catch(e) { }
+            }
+        }
+);
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.Sphere = Class.create();
+
+Flog.RayTracer.Shape.Sphere.prototype = {
+    initialize : function(pos, radius, material) {
+        try {
+            this.radius = radius;
+            this.position = pos;
+            this.material = material;
+
+            randomException();
+        } catch(e) { }
+    },
+
+    intersect: function(ray){
+        try {
+            var info = new Flog.RayTracer.IntersectionInfo();
+            info.shape = this;
+
+            var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position);
+
+            var B = dst.dot(ray.direction);
+            var C = dst.dot(dst) - (this.radius * this.radius);
+            var D = (B * B) - C;
+
+            if(D &gt; 0){ // intersection!
+                info.isHit = true;
+                info.distance = (-B) - Math.sqrt(D);
+                info.position = Flog.RayTracer.Vector.prototype.add(
+                        ray.position,
+                        Flog.RayTracer.Vector.prototype.multiplyScalar(
+                            ray.direction,
+                            info.distance
+                            )
+                        );
+                info.normal = Flog.RayTracer.Vector.prototype.subtract(
+                        info.position,
+                        this.position
+                        ).normalize();
+
+                info.color = this.material.getColor(0,0);
+            } else {
+                info.isHit = false;
+            }
+
+            randomException();
+        } catch(e) { }
+        return info;
+    },
+
+    toString : function () {
+        try {
+            return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+if(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
+
+Flog.RayTracer.Shape.Plane = Class.create();
+
+Flog.RayTracer.Shape.Plane.prototype = {
+    d: 0.0,
+
+    initialize : function(pos, d, material) {
+        try {
+            this.position = pos;
+            this.d = d;
+            this.material = material;
+            randomException();
+        } catch(e) { }
+    },
+
+    intersect: function(ray){
+        try {
+            var info = new Flog.RayTracer.IntersectionInfo();
+
+            var Vd = this.position.dot(ray.direction);
+            if(Vd == 0) return info; // no intersection
+
+            var t = -(this.position.dot(ray.position) + this.d) / Vd;
+            if(t &lt;= 0) return info;
+
+            info.shape = this;
+            info.isHit = true;
+            info.position = Flog.RayTracer.Vector.prototype.add(
+                    ray.position,
+                    Flog.RayTracer.Vector.prototype.multiplyScalar(
+                        ray.direction,
+                        t
+                        )
+                    );
+            info.normal = this.position;
+            info.distance = t;
+
+            if(this.material.hasTexture){
+                var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x);
+                var vV = vU.cross(this.position);
+                var u = info.position.dot(vU);
+                var v = info.position.dot(vV);
+                info.color = this.material.getColor(u,v);
+            } else {
+                info.color = this.material.getColor(0,0);
+            }
+
+            randomException();
+        } catch(e) { }
+        return info;
+    },
+
+    toString : function () {
+        try {
+            return 'Plane [' + this.position + ', d=' + this.d + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.IntersectionInfo = Class.create();
+
+Flog.RayTracer.IntersectionInfo.prototype = {
+    isHit: false,
+    hitCount: 0,
+    shape: null,
+    position: null,
+    normal: null,
+    color: null,
+    distance: null,
+
+    initialize : function() {
+        try {
+            this.color = new Flog.RayTracer.Color(0,0,0);
+            randomException();
+        } catch(e) { }
+    },
+
+    toString : function () {
+        try {
+            return 'Intersection [' + this.position + ']';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Camera = Class.create();
+
+Flog.RayTracer.Camera.prototype = {
+    position: null,
+    lookAt: null,
+    equator: null,
+    up: null,
+    screen: null,
+
+    initialize : function(pos, lookAt, up) {
+        try {
+            this.position = pos;
+            this.lookAt = lookAt;
+            this.up = up;
+            this.equator = lookAt.normalize().cross(this.up);
+            this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt);
+            randomException();
+        } catch(e) { }
+    },
+
+    getRay: function(vx, vy){
+        try {
+            var pos = Flog.RayTracer.Vector.prototype.subtract(
+                    this.screen,
+                    Flog.RayTracer.Vector.prototype.subtract(
+                        Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx),
+                        Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy)
+                        )
+                    );
+            pos.y = pos.y * -1;
+            var dir = Flog.RayTracer.Vector.prototype.subtract(
+                    pos,
+                    this.position
+                    );
+
+            var ray = new Flog.RayTracer.Ray(pos, dir.normalize());
+
+            randomException();
+        } catch(e) { }
+        return ray;
+    },
+
+    toString : function () {
+        try {
+            return 'Ray []';
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Background = Class.create();
+
+Flog.RayTracer.Background.prototype = {
+    color : null,
+    ambience : 0.0,
+
+    initialize : function(color, ambience) {
+        try {
+            this.color = color;
+            this.ambience = ambience;
+            randomException();
+        } catch(e) { }
+    }
+}
+/* Fake a Flog.* namespace */
+if(typeof(Flog) == 'undefined') var Flog = {};
+if(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
+
+Flog.RayTracer.Engine = Class.create();
+
+Flog.RayTracer.Engine.prototype = {
+    canvas: null, /* 2d context we can render to */
+
+    initialize: function(options){
+        try {
+            this.options = Object.extend({
+                canvasHeight: 100,
+                canvasWidth: 100,
+                pixelWidth: 2,
+                pixelHeight: 2,
+                renderDiffuse: false,
+                renderShadows: false,
+                renderHighlights: false,
+                renderReflections: false,
+                rayDepth: 2
+            }, options || {});
+
+            this.options.canvasHeight /= this.options.pixelHeight;
+            this.options.canvasWidth /= this.options.pixelWidth;
+
+            randomException();
+        } catch(e) { }
+
+        /* TODO: dynamically include other scripts */
+    },
+
+    setPixel: function(x, y, color){
+        try {
+            var pxW, pxH;
+            pxW = this.options.pixelWidth;
+            pxH = this.options.pixelHeight;
+
+            if (this.canvas) {
+                this.canvas.fillStyle = color.toString();
+                this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
+            } else {
+                if (x ===  y) {
+                    checkNumber += color.brightness();
+                }
+                // print(x * pxW, y * pxH, pxW, pxH);
+            }
+
+            randomException();
+        } catch(e) { }
+    },
+
+    renderScene: function(scene, canvas){
+        try {
+            checkNumber = 0;
+            /* Get canvas */
+            if (canvas) {
+                this.canvas = canvas.getContext(&quot;2d&quot;);
+            } else {
+                this.canvas = null;
+            }
+
+            var canvasHeight = this.options.canvasHeight;
+            var canvasWidth = this.options.canvasWidth;
+
+            for(var y=0; y &lt; canvasHeight; y++){
+                for(var x=0; x &lt; canvasWidth; x++){
+                    try {
+                        var yp = y * 1.0 / canvasHeight * 2 - 1;
+                        var xp = x * 1.0 / canvasWidth * 2 - 1;
+
+                        var ray = scene.camera.getRay(xp, yp);
+
+                        var color = this.getPixelColor(ray, scene);
+
+                        this.setPixel(x, y, color);
+
+                        randomException();
+                    } catch(e) { }
+                }
+            }
+        } catch(e) { }
+        if (checkNumber !== 2321) {
+            throw new Error(&quot;Scene rendered incorrectly&quot;);
+        }
+    },
+
+    getPixelColor: function(ray, scene){
+        try {
+            var info = this.testIntersection(ray, scene, null);
+            if(info.isHit){
+                var color = this.rayTrace(info, ray, scene, 0);
+                return color;
+            }
+            return scene.background.color;
+        } catch(e) { }
+    },
+
+    testIntersection: function(ray, scene, exclude){
+        try {
+            var hits = 0;
+            var best = new Flog.RayTracer.IntersectionInfo();
+            best.distance = 2000;
+
+            for(var i=0; i&lt;scene.shapes.length; i++){
+                try {
+                    var shape = scene.shapes[i];
+
+                    if(shape != exclude){
+                        var info = shape.intersect(ray);
+                        if(info.isHit &amp;&amp; info.distance &gt;= 0 &amp;&amp; info.distance &lt; best.distance){
+                            best = info;
+                            hits++;
+                        }
+                    }
+
+                    randomException();
+                } catch(e) { }
+            }
+            best.hitCount = hits;
+
+            randomException();
+        } catch(e) { }
+        return best;
+    },
+
+    getReflectionRay: function(P,N,V){
+        try {
+            var c1 = -N.dot(V);
+            var R1 = Flog.RayTracer.Vector.prototype.add(
+                    Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1),
+                    V
+                    );
+
+            randomException();
+        } catch(e) { }
+        return new Flog.RayTracer.Ray(P, R1);
+    },
+
+    rayTrace: function(info, ray, scene, depth){
+        // Calc ambient
+        try {
+            var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience);
+            var oldColor = color;
+            var shininess = Math.pow(10, info.shape.material.gloss + 1);
+
+            for(var i=0; i&lt;scene.lights.length; i++){
+                try {
+                    var light = scene.lights[i];
+
+                    // Calc diffuse lighting
+                    var v = Flog.RayTracer.Vector.prototype.subtract(
+                            light.position,
+                            info.position
+                            ).normalize();
+
+                    if(this.options.renderDiffuse){
+                        var L = v.dot(info.normal);
+                        if(L &gt; 0.0){
+                            color = Flog.RayTracer.Color.prototype.add(
+                                    color,
+                                    Flog.RayTracer.Color.prototype.multiply(
+                                        info.color,
+                                        Flog.RayTracer.Color.prototype.multiplyScalar(
+                                            light.color,
+                                            L
+                                            )
+                                        )
+                                    );
+                        }
+                    }
+
+                    randomException();
+                } catch(e) { }
+
+                try {
+                    // The greater the depth the more accurate the colours, but
+                    // this is exponentially (!) expensive
+                    if(depth &lt;= this.options.rayDepth){
+                        // calculate reflection ray
+                        if(this.options.renderReflections &amp;&amp; info.shape.material.reflection &gt; 0)
+                        {
+                            var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
+                            var refl = this.testIntersection(reflectionRay, scene, info.shape);
+
+                            if (refl.isHit &amp;&amp; refl.distance &gt; 0){
+                                refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
+                            } else {
+                                refl.color = scene.background.color;
+                            }
+
+                            color = Flog.RayTracer.Color.prototype.blend(
+                                    color,
+                                    refl.color,
+                                    info.shape.material.reflection
+                                    );
+                        }
+
+                        // Refraction
+                        /* TODO */
+                    }
+                    randomException();
+                }  catch(e) { }
+
+                /* Render shadows and highlights */
+
+                var shadowInfo = new Flog.RayTracer.IntersectionInfo();
+
+                if(this.options.renderShadows){
+                    var shadowRay = new Flog.RayTracer.Ray(info.position, v);
+
+                    shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
+                    if(shadowInfo.isHit &amp;&amp; shadowInfo.shape != info.shape /*&amp;&amp; shadowInfo.shape.type != 'PLANE'*/){
+                        var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5);
+                        var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5));
+                        color = Flog.RayTracer.Color.prototype.addScalar(vA,dB);
+                    }
+                }
+
+                try {
+                    // Phong specular highlights
+                    if(this.options.renderHighlights &amp;&amp; !shadowInfo.isHit &amp;&amp; info.shape.material.gloss &gt; 0){
+                        var Lv = Flog.RayTracer.Vector.prototype.subtract(
+                                info.shape.position,
+                                light.position
+                                ).normalize();
+
+                        var E = Flog.RayTracer.Vector.prototype.subtract(
+                                scene.camera.position,
+                                info.shape.position
+                                ).normalize();
+
+                        var H = Flog.RayTracer.Vector.prototype.subtract(
+                                E,
+                                Lv
+                                ).normalize();
+
+                        var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess);
+                        color = Flog.RayTracer.Color.prototype.add(
+                                Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight),
+                                color
+                                );
+                    }
+                    randomException();
+                } catch(e) { }
+            }
+            color.limit();
+
+            randomException();
+        } catch(e) { }
+        return color;
+    }
+};
+
+
+function renderScene(){
+    try {
+        var scene = new Flog.RayTracer.Scene();
+
+        scene.camera = new Flog.RayTracer.Camera(
+                new Flog.RayTracer.Vector(0, 0, -15),
+                new Flog.RayTracer.Vector(-0.2, 0, 5),
+                new Flog.RayTracer.Vector(0, 1, 0)
+                );
+
+        scene.background = new Flog.RayTracer.Background(
+                new Flog.RayTracer.Color(0.5, 0.5, 0.5),
+                0.4
+                );
+
+        var sphere = new Flog.RayTracer.Shape.Sphere(
+                new Flog.RayTracer.Vector(-1.5, 1.5, 2),
+                1.5,
+                new Flog.RayTracer.Material.Solid(
+                    new Flog.RayTracer.Color(0,0.5,0.5),
+                    0.3,
+                    0.0,
+                    0.0,
+                    2.0
+                    )
+                );
+
+        var sphere1 = new Flog.RayTracer.Shape.Sphere(
+                new Flog.RayTracer.Vector(1, 0.25, 1),
+                0.5,
+                new Flog.RayTracer.Material.Solid(
+                    new Flog.RayTracer.Color(0.9,0.9,0.9),
+                    0.1,
+                    0.0,
+                    0.0,
+                    1.5
+                    )
+                );
+
+        var plane = new Flog.RayTracer.Shape.Plane(
+                new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(),
+                1.2,
+                new Flog.RayTracer.Material.Chessboard(
+                    new Flog.RayTracer.Color(1,1,1),
+                    new Flog.RayTracer.Color(0,0,0),
+                    0.2,
+                    0.0,
+                    1.0,
+                    0.7
+                    )
+                );
+
+        scene.shapes.push(plane);
+        scene.shapes.push(sphere);
+        scene.shapes.push(sphere1);
+
+        var light = new Flog.RayTracer.Light(
+                new Flog.RayTracer.Vector(5, 10, -1),
+                new Flog.RayTracer.Color(0.8, 0.8, 0.8)
+                );
+
+        var light1 = new Flog.RayTracer.Light(
+                new Flog.RayTracer.Vector(-3, 5, -15),
+                new Flog.RayTracer.Color(0.8, 0.8, 0.8),
+                100
+                );
+
+        scene.lights.push(light);
+        scene.lights.push(light1);
+
+        var imageWidth = 100; // $F('imageWidth');
+        var imageHeight = 100; // $F('imageHeight');
+        var pixelSize = &quot;5,5&quot;.split(','); //  $F('pixelSize').split(',');
+        var renderDiffuse = true; // $F('renderDiffuse');
+        var renderShadows = true; // $F('renderShadows');
+        var renderHighlights = true; // $F('renderHighlights');
+        var renderReflections = true; // $F('renderReflections');
+        var rayDepth = 2;//$F('rayDepth');
+
+        var raytracer = new Flog.RayTracer.Engine(
+                {
+                    canvasWidth: imageWidth,
+                    canvasHeight: imageHeight,
+                    pixelWidth: pixelSize[0],
+                    pixelHeight: pixelSize[1],
+                    &quot;renderDiffuse&quot;: renderDiffuse,
+                    &quot;renderHighlights&quot;: renderHighlights,
+                    &quot;renderShadows&quot;: renderShadows,
+                    &quot;renderReflections&quot;: renderReflections,
+                    &quot;rayDepth&quot;: rayDepth
+                }
+                );
+
+        raytracer.renderScene(scene, null, 0);
+        randomException();
+    } catch(e) { }
+}
+
+for (var i = 0; i &lt; 6; ++i)
+    renderScene();
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressv8raytracewithemptytrycatchexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch-expected.txt (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch-expected.txt        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/v8-raytrace-with-empty-try-catch
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressv8raytracewithemptytrycatchhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch.html (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/v8-raytrace-with-empty-try-catch.html        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/v8-raytrace-with-empty-try-catch.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressv8raytracewithtrycatchexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch-expected.txt (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch-expected.txt        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/v8-raytrace-with-try-catch
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressv8raytracewithtrycatchhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch.html (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/v8-raytrace-with-try-catch.html        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/v8-raytrace-with-try-catch.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -185,6 +185,7 @@
</span><span class="cx">     dfg/DFGFixupPhase.cpp
</span><span class="cx">     dfg/DFGFlushFormat.cpp
</span><span class="cx">     dfg/DFGFlushedAt.cpp
</span><ins>+    dfg/DFGLiveCatchVariablePreservationPhase.cpp
</ins><span class="cx">     dfg/DFGFrozenValue.cpp
</span><span class="cx">     dfg/DFGFunctionWhitelist.cpp
</span><span class="cx">     dfg/DFGGraph.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -1,3 +1,209 @@
</span><ins>+2015-09-17  Saam barati  &lt;sbarati@apple.com&gt;
+
+        Implement try/catch in the DFG.
+        https://bugs.webkit.org/show_bug.cgi?id=147374
+
+        Reviewed by Filip Pizlo.
+
+        This patch implements try/catch inside the DFG JIT.
+        It also prevents tier up to the FTL for any functions
+        that have an op_catch in them that are DFG compiled.
+
+        This patch accomplishes implementing try/catch inside
+        the DFG by OSR exiting to op_catch when an exception is thrown.
+        We can OSR exit from an exception inside the DFG in two ways:
+        1) We have a JS call (can also be via implicit getter/setter in GetById/PutById)
+        2) We have an exception when returing from a callOperation
+
+        In the case of (1), we get to the OSR exit from genericUnwind because
+        the exception was thrown in a child call frame. This means these
+        OSR exits must act as defacto op_catches (even though we will still OSR
+        exit to a baseline op_catch). That means they must restore the stack pointer
+        and call frame.
+
+        In the case of (2), we can skip genericUnwind because we know the exception 
+        check will take us to a particular OSR exit. Instead, we link these
+        exception checks as jumps to a particular OSR exit.
+
+        Both types of OSR exits will exit into op_catch inside the baseline JIT.
+        Because they exit to op_catch, these OSR exits must set callFrameForCatch
+        to the proper call frame pointer.
+
+        We &quot;handle&quot; all exceptions inside the machine frame of the DFG code
+        block. This means the machine code block is responsible for &quot;catching&quot;
+        exceptions of any inlined frames' try/catch. OSR exit will then exit to 
+        the proper baseline CodeBlock after reifying the inlined frames
+        (DFG::OSRExit::m_codeOrigin corresponds to the op_catch we will exit to). 
+        Also, genericUnwind will never consult an inlined call frame's CodeBlock to 
+        see if they can catch the exception because they can't. We always unwind to the 
+        next machine code block frame. The DFG CodeBlock changes how the exception 
+        handler table is keyed: it is now keyed by CallSiteIndex for DFG code blocks. 
+
+        So, when consulting call sites that throw, we keep track of the CallSiteIndex,
+        and the HandlerInfo for the corresponding baseline exception handler for
+        that particular CallSiteIndex (if an exception at that call site will be caught). 
+        Then, when we're inside DFG::JITCompiler::link(), we install new HandlerInfo's
+        inside the DFG CodeBlock and key it by the corresponding CallSiteIndex.
+        (The CodeBlock only has HandlerInfos for the OSR exits that are to be arrived
+        at from genericUnwind).
+
+        Also, each OSR exit will know if it acting as an exception handler, and
+        whether or not it will be arrived at from genericUnwind. When we know we 
+        will arrive at an OSR exit from genericUnwind, we set the corresponding 
+        HandlerInfo's nativeCode CodeLocationLabel field to be the OSR exit.
+
+        This patch also introduces a new Phase inside the DFG that ensures
+        that DFG CodeBlocks that handle exceptions take the necessary
+        steps to keep live variables at &quot;op_catch&quot; live according the
+        OSR exit value recovery machinery. We accomplish this by flushing
+        all live op_catch variables to the stack when inside a &quot;try&quot; block.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::handlerForBytecodeOffset):
+        (JSC::CodeBlock::handlerForIndex):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::clearExceptionHandlers):
+        (JSC::CodeBlock::appendExceptionHandler):
+        * bytecode/PreciseJumpTargets.cpp:
+        (JSC::computePreciseJumpTargets):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::getLocal):
+        (JSC::DFG::ByteCodeParser::setLocal):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * dfg/DFGCommonData.cpp:
+        (JSC::DFG::CommonData::addCodeOrigin):
+        (JSC::DFG::CommonData::lastCallSite):
+        (JSC::DFG::CommonData::shrinkToFit):
+        * dfg/DFGCommonData.h:
+        * dfg/DFGGraph.h:
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::linkOSRExits):
+        (JSC::DFG::JITCompiler::link):
+        (JSC::DFG::JITCompiler::compile):
+        (JSC::DFG::JITCompiler::noticeOSREntry):
+        (JSC::DFG::JITCompiler::appendExceptionHandlingOSRExit):
+        (JSC::DFG::JITCompiler::willCatchExceptionInMachineFrame):
+        (JSC::DFG::JITCompiler::exceptionCheck):
+        (JSC::DFG::JITCompiler::recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::emitStoreCodeOrigin):
+        (JSC::DFG::JITCompiler::emitStoreCallSiteIndex):
+        (JSC::DFG::JITCompiler::appendCall):
+        (JSC::DFG::JITCompiler::exceptionCheckWithCallFrameRollback):
+        (JSC::DFG::JITCompiler::blockHeads):
+        (JSC::DFG::JITCompiler::exceptionCheck): Deleted.
+        * dfg/DFGLiveCatchVariablePreservationPhase.cpp: Added.
+        (JSC::DFG::FlushLiveCatchVariablesInsertionPhase::FlushLiveCatchVariablesInsertionPhase):
+        (JSC::DFG::FlushLiveCatchVariablesInsertionPhase::run):
+        (JSC::DFG::FlushLiveCatchVariablesInsertionPhase::willCatchException):
+        (JSC::DFG::FlushLiveCatchVariablesInsertionPhase::handleBlock):
+        (JSC::DFG::FlushLiveCatchVariablesInsertionPhase::newVariableAccessData):
+        (JSC::DFG::performLiveCatchVariablePreservationPhase):
+        * dfg/DFGLiveCatchVariablePreservationPhase.h: Added.
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::OSRExit::OSRExit):
+        (JSC::DFG::OSRExit::setPatchableCodeOffset):
+        * dfg/DFGOSRExit.h:
+        (JSC::DFG::OSRExit::considerAddingAsFrequentExitSite):
+        * dfg/DFGOSRExitCompiler.cpp:
+        * dfg/DFGOSRExitCompiler32_64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGOSRExitCompiler64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGOSRExitCompilerCommon.cpp:
+        (JSC::DFG::osrWriteBarrier):
+        (JSC::DFG::adjustAndJumpToTarget):
+        * dfg/DFGOSRExitCompilerCommon.h:
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGSlowPathGenerator.h:
+        (JSC::DFG::SlowPathGenerator::SlowPathGenerator):
+        (JSC::DFG::SlowPathGenerator::~SlowPathGenerator):
+        (JSC::DFG::SlowPathGenerator::generate):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::cachedGetById):
+        (JSC::DFG::SpeculativeJIT::cachedPutById):
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::cachedGetById):
+        (JSC::DFG::SpeculativeJIT::cachedPutById):
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * dfg/DFGTierUpCheckInjectionPhase.cpp:
+        (JSC::DFG::TierUpCheckInjectionPhase::run):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileStub):
+        * interpreter/Interpreter.cpp:
+        (JSC::GetCatchHandlerFunctor::operator()):
+        (JSC::UnwindFunctor::operator()):
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::gotoNextFrame):
+        (JSC::StackVisitor::unwindToMachineCodeBlockFrame):
+        (JSC::StackVisitor::readFrame):
+        * interpreter/StackVisitor.h:
+        (JSC::StackVisitor::operator*):
+        (JSC::StackVisitor::operator-&gt;):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::emitExceptionCheck):
+        (JSC::AssemblyHelpers::emitNonPatchableExceptionCheck):
+        (JSC::AssemblyHelpers::emitStoreStructureWithTypeInfo):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::emitCount):
+        * jit/JITExceptions.cpp:
+        (JSC::genericUnwind):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_catch):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_catch):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/VM.h:
+        (JSC::VM::clearException):
+        (JSC::VM::clearLastException):
+        (JSC::VM::addressOfCallFrameForCatch):
+        (JSC::VM::exception):
+        (JSC::VM::addressOfException):
+        * tests/stress/dfg-exception-try-catch-in-constructor-with-inlined-throw.js: Added.
+        (f):
+        (bar):
+        (Foo):
+        * tests/stress/es6-for-of-loop-exception.js: Added.
+        (assert):
+        (shouldThrowInvalidConstAssignment):
+        (baz):
+        (foo):
+        * tests/stress/exception-dfg-inlined-frame-not-strict-equal.js: Added.
+        (assert):
+        (o.valueOf):
+        (o.toString):
+        (read):
+        (bar):
+        (foo):
+        * tests/stress/exception-dfg-not-strict-equal.js: Added.
+        (foo):
+        (o.valueOf):
+        (o.toString):
+        (assert):
+        (shouldDoSomethingInFinally):
+        (catch):
+        * tests/stress/exception-dfg-operation-read-value.js: Added.
+        (assert):
+        (o.valueOf):
+        (o.toString):
+        (read):
+        (foo):
+        * tests/stress/exception-dfg-throw-from-catch-block.js: Added.
+        (assert):
+        (baz):
+        (bar):
+        (foo):
+
</ins><span class="cx"> 2015-09-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         0.0 should really be 0.0
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -421,6 +421,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFixupPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFlushedAt.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFlushFormat.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGLiveCatchVariablePreservationPhase.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFrozenValue.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFunctionWhitelist.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGGraph.cpp&quot; /&gt;
</span><span class="lines">@@ -1150,6 +1151,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFixupPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFlushedAt.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFlushFormat.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGLiveCatchVariablePreservationPhase.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGForAllKills.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFPRInfo.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFrozenValue.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -1242,6 +1242,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFlushFormat.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGLiveCatchVariablePreservationPhase.cpp&quot;&gt;
+      &lt;Filter&gt;dfg&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGFunctionWhitelist.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -3706,6 +3709,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFlushFormat.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGLiveCatchVariablePreservationPhase.h&quot;&gt;
+      &lt;Filter&gt;dfg&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGFPRInfo.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -1033,6 +1033,8 @@
</span><span class="cx">                 7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; };
</span><span class="cx">                 797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */; };
+                79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 79EE0BFF1B4AFB85000385C9 /* VariableEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */; };
</span><span class="cx">                 79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 79F8FC1E1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */; };
</span><span class="lines">@@ -2866,6 +2868,8 @@
</span><span class="cx">                 796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLiveCatchVariablePreservationPhase.cpp; path = dfg/DFGLiveCatchVariablePreservationPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLiveCatchVariablePreservationPhase.h; path = dfg/DFGLiveCatchVariablePreservationPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 79EE0BFD1B4AFB85000385C9 /* VariableEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableEnvironment.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79EE0BFE1B4AFB85000385C9 /* VariableEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VariableEnvironment.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMaximalFlushInsertionPhase.cpp; path = dfg/DFGMaximalFlushInsertionPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5229,6 +5233,8 @@
</span><span class="cx">                                 0F9D339517FFC4E60073C2BC /* DFGFlushedAt.h */,
</span><span class="cx">                                 A7D89CE817A0B8CC00773AD8 /* DFGFlushFormat.cpp */,
</span><span class="cx">                                 A7D89CE917A0B8CC00773AD8 /* DFGFlushFormat.h */,
</span><ins>+                                79C4B15B1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp */,
+                                79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */,
</ins><span class="cx">                                 0F2DD8101AB3D8BE00BBB8E8 /* DFGForAllKills.h */,
</span><span class="cx">                                 0F69CC86193AC60A0045759E /* DFGFrozenValue.cpp */,
</span><span class="cx">                                 0F69CC87193AC60A0045759E /* DFGFrozenValue.h */,
</span><span class="lines">@@ -5924,6 +5930,7 @@
</span><span class="cx">                                 A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
</span><span class="cx">                                 0F898F321B27689F0083A33C /* DFGIntegerRangeOptimizationPhase.h in Headers */,
</span><span class="cx">                                 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
</span><ins>+                                79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */,
</ins><span class="cx">                                 79F8FC1F1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h in Headers */,
</span><span class="cx">                                 99F1A7011B98FBEC00463B26 /* InspectorFrontendRouter.h in Headers */,
</span><span class="cx">                                 7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */,
</span><span class="lines">@@ -8000,6 +8007,7 @@
</span><span class="cx">                                 A1587D711B4DC14100D69849 /* IntlDateTimeFormatPrototype.cpp in Sources */,
</span><span class="cx">                                 0F2B670A17B6B5AB00A7AE3F /* TypedArrayType.cpp in Sources */,
</span><span class="cx">                                 52C952B919A28A1C0069B386 /* TypeProfiler.cpp in Sources */,
</span><ins>+                                79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */,
</ins><span class="cx">                                 0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
</span><span class="cx">                                 0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,
</span><span class="cx">                                 0FF42743158EBE91004CB9FF /* udis86_input.c in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -2857,7 +2857,11 @@
</span><span class="cx"> HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(bytecodeOffset &lt; instructions().size());
</span><ins>+    return handlerForIndex(bytecodeOffset, requiredHandler);
+}
</ins><span class="cx"> 
</span><ins>+HandlerInfo* CodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler)
+{
</ins><span class="cx">     if (!m_rareData)
</span><span class="cx">         return 0;
</span><span class="cx">     
</span><span class="lines">@@ -2869,7 +2873,8 @@
</span><span class="cx"> 
</span><span class="cx">         // Handlers are ordered innermost first, so the first handler we encounter
</span><span class="cx">         // that contains the source address is the correct handler to use.
</span><del>-        if (handler.start &lt;= bytecodeOffset &amp;&amp; handler.end &gt; bytecodeOffset)
</del><ins>+        // This index used is either the BytecodeOffset or a CallSiteIndex.
+        if (handler.start &lt;= index &amp;&amp; handler.end &gt; index)
</ins><span class="cx">             return &amp;handler;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -195,6 +195,7 @@
</span><span class="cx">         AnyHandler
</span><span class="cx">     };
</span><span class="cx">     HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler);
</span><ins>+    HandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler);
</ins><span class="cx">     unsigned lineNumberForBytecodeOffset(unsigned bytecodeOffset);
</span><span class="cx">     unsigned columnNumberForBytecodeOffset(unsigned bytecodeOffset);
</span><span class="cx">     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int&amp; divot,
</span><span class="lines">@@ -910,6 +911,18 @@
</span><span class="cx">         EvalCodeCache m_evalCodeCache;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    void clearExceptionHandlers()
+    {
+        if (m_rareData)
+            m_rareData-&gt;m_exceptionHandlers.clear();
+    }
+
+    void appendExceptionHandler(const HandlerInfo&amp; handler)
+    {
+        createRareDataIfNecessary(); // We may be handling the exception of an inlined call frame.
+        m_rareData-&gt;m_exceptionHandlers.append(handler);
+    }
+
</ins><span class="cx"> protected:
</span><span class="cx">     virtual void visitWeakReferences(SlotVisitor&amp;) override;
</span><span class="cx">     virtual void finalizeUnconditionally() override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePreciseJumpTargetscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -93,9 +93,12 @@
</span><span class="cx">     if (!codeBlock-&gt;numberOfJumpTargets())
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    for (unsigned i = codeBlock-&gt;numberOfExceptionHandlers(); i--;)
</del><ins>+    for (unsigned i = codeBlock-&gt;numberOfExceptionHandlers(); i--;) {
</ins><span class="cx">         out.append(codeBlock-&gt;exceptionHandler(i).target);
</span><del>-    
</del><ins>+        out.append(codeBlock-&gt;exceptionHandler(i).start);
+        out.append(codeBlock-&gt;exceptionHandler(i).end);
+    }
+
</ins><span class="cx">     Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
</span><span class="cx">     Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
</span><span class="cx">     unsigned instructionCount = codeBlock-&gt;instructions().size();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -434,7 +434,6 @@
</span><span class="cx">         m_currentBlock-&gt;variablesAtTail.local(local) = node;
</span><span class="cx">         return node;
</span><span class="cx">     }
</span><del>-
</del><span class="cx">     Node* setLocal(const CodeOrigin&amp; semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
</span><span class="cx">     {
</span><span class="cx">         CodeOrigin oldSemanticOrigin = m_currentSemanticOrigin;
</span><span class="lines">@@ -3780,6 +3779,10 @@
</span><span class="cx">             flushForTerminal();
</span><span class="cx">             addToGraph(Unreachable);
</span><span class="cx">             LAST_OPCODE(op_throw_static_error);
</span><ins>+
+        case op_catch:
+            m_graph.m_hasExceptionHandlers = true;
+            NEXT_OPCODE(op_catch);
</ins><span class="cx">             
</span><span class="cx">         case op_call:
</span><span class="cx">             handleCall(currentInstruction, Call, CodeForCall);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -211,6 +211,7 @@
</span><span class="cx">     case op_new_arrow_func_exp:
</span><span class="cx">     case op_create_lexical_environment:
</span><span class="cx">     case op_get_parent_scope:
</span><ins>+    case op_catch:
</ins><span class="cx">         return CanCompileAndInline;
</span><span class="cx"> 
</span><span class="cx">     case op_put_to_scope: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommonData.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommonData.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommonData.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -57,6 +57,12 @@
</span><span class="cx">     return CallSiteIndex(index);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CallSiteIndex CommonData::lastCallSite() const
+{
+    ASSERT(codeOrigins.size());
+    return CallSiteIndex(codeOrigins.size() - 1);
+}
+
</ins><span class="cx"> void CommonData::shrinkToFit()
</span><span class="cx"> {
</span><span class="cx">     codeOrigins.shrinkToFit();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommonData.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommonData.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommonData.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -80,6 +80,7 @@
</span><span class="cx">     
</span><span class="cx">     void notifyCompilingStructureTransition(Plan&amp;, CodeBlock*, Node*);
</span><span class="cx">     CallSiteIndex addCodeOrigin(CodeOrigin);
</span><ins>+    CallSiteIndex lastCallSite() const;
</ins><span class="cx">     
</span><span class="cx">     void shrinkToFit();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -875,6 +875,7 @@
</span><span class="cx">     PlanStage m_planStage { PlanStage::Initial };
</span><span class="cx">     RefCountState m_refCountState;
</span><span class="cx">     bool m_hasDebuggerEnabled;
</span><ins>+    bool m_hasExceptionHandlers { false };
</ins><span class="cx"> private:
</span><span class="cx">     
</span><span class="cx">     void handleSuccessor(Vector&lt;BasicBlock*, 16&gt;&amp; worklist, BasicBlock*, BasicBlock* successor);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -85,6 +85,18 @@
</span><span class="cx">             failureJumps.link(this);
</span><span class="cx">         else
</span><span class="cx">             info.m_replacementDestination = label();
</span><ins>+
+        if (exit.m_willArriveAtOSRExitFromGenericUnwind) {
+            // We are acting as a defacto op_catch because we arrive here from genericUnwind().
+            // So, we must restore our call frame and stack pointer.
+            loadPtr(vm()-&gt;addressOfCallFrameForCatch(), GPRInfo::callFrameRegister);
+            addPtr(TrustedImm32(graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, stackPointerRegister);
+            restoreCalleeSavesFromVMCalleeSavesBuffer();
+        } else if (exit.m_isExceptionHandler) {
+            ASSERT(!exit.m_willArriveAtOSRExitFromGenericUnwind);
+            copyCalleeSavesToVMCalleeSavesBuffer();
+        }
+
</ins><span class="cx">         jitAssertHasValidCallFrame();
</span><span class="cx">         store32(TrustedImm32(i), &amp;vm()-&gt;osrExitIndex);
</span><span class="cx">         exit.setPatchableCodeOffset(patchableJump());
</span><span class="lines">@@ -283,9 +295,27 @@
</span><span class="cx">         }
</span><span class="cx">     } else
</span><span class="cx">         ASSERT(!m_exitSiteLabels.size());
</span><del>-    
</del><ins>+
</ins><span class="cx">     m_jitCode-&gt;common.compilation = m_graph.compilation();
</span><span class="cx">     
</span><ins>+    // Link new DFG exception handlers and remove baseline JIT handlers.
+    m_codeBlock-&gt;clearExceptionHandlers();
+    for (unsigned  i = 0; i &lt; m_exceptionHandlerOSRExitCallSites.size(); i++) {
+        OSRExitCompilationInfo&amp; info = m_exceptionHandlerOSRExitCallSites[i].exitInfo;
+        if (info.m_replacementDestination.isSet()) {
+            // If this is is *not* set, it means that we already jumped to the OSR exit in pure generated control flow.
+            // i.e, we explicitly emitted an exceptionCheck that we know will be caught in this machine frame.
+            // If this *is set*, it means we will be landing at this code location from genericUnwind from an
+            // exception thrown in a child call frame.
+            CodeLocationLabel catchLabel = linkBuffer.locationOf(info.m_replacementDestination);
+            HandlerInfo newExceptionHandler = m_exceptionHandlerOSRExitCallSites[i].baselineExceptionHandler;
+            CallSiteIndex callSite = m_exceptionHandlerOSRExitCallSites[i].callSiteIndex;
+            newExceptionHandler.start = callSite.bits();
+            newExceptionHandler.end = callSite.bits() + 1;
+            newExceptionHandler.nativeCode = catchLabel;
+            m_codeBlock-&gt;appendExceptionHandler(newExceptionHandler);
+        }
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JITCompiler::compile()
</span><span class="lines">@@ -337,7 +367,7 @@
</span><span class="cx">     
</span><span class="cx">     link(*linkBuffer);
</span><span class="cx">     m_speculative-&gt;linkOSREntries(*linkBuffer);
</span><del>-    
</del><ins>+
</ins><span class="cx">     m_jitCode-&gt;shrinkToFit();
</span><span class="cx">     codeBlock()-&gt;shrinkToFit(CodeBlock::LateShrink);
</span><span class="cx"> 
</span><span class="lines">@@ -522,6 +552,84 @@
</span><span class="cx">     entry-&gt;m_reshufflings.shrinkToFit();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JITCompiler::appendExceptionHandlingOSRExit(unsigned eventStreamIndex, CodeOrigin opCatchOrigin, HandlerInfo* exceptionHandler, CallSiteIndex callSite, MacroAssembler::JumpList jumpsToFail)
+{
+    OSRExit exit(Uncountable, JSValueRegs(), graph().methodOfGettingAValueProfileFor(nullptr), m_speculative.get(), eventStreamIndex);
+    exit.m_willArriveAtOSRExitFromGenericUnwind = jumpsToFail.empty(); // If jumps are empty, we're going to jump here from genericUnwind from a child call frame.
+    exit.m_isExceptionHandler = true;
+    exit.m_codeOrigin = opCatchOrigin;
+    OSRExitCompilationInfo&amp; exitInfo = appendExitInfo(jumpsToFail);
+    jitCode()-&gt;appendOSRExit(exit);
+    m_exceptionHandlerOSRExitCallSites.append(ExceptionHandlingOSRExitInfo { exitInfo, *exceptionHandler, callSite });
+}
+
+bool JITCompiler::willCatchExceptionInMachineFrame(CodeOrigin codeOrigin, CodeOrigin&amp; opCatchOriginOut, HandlerInfo*&amp; catchHandlerOut)
+{
+    unsigned bytecodeIndexToCheck = codeOrigin.bytecodeIndex;
+    while (1) {
+        InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame;
+        CodeBlock* codeBlock = m_graph.baselineCodeBlockFor(inlineCallFrame);
+        if (HandlerInfo* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeIndexToCheck)) {
+            opCatchOriginOut = CodeOrigin(handler-&gt;target, inlineCallFrame);
+            catchHandlerOut = handler;
+            return true;
+        }
+
+        if (!inlineCallFrame)
+            return false;
+
+        bytecodeIndexToCheck = inlineCallFrame-&gt;caller.bytecodeIndex;
+        codeOrigin = codeOrigin.inlineCallFrame-&gt;caller;
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void JITCompiler::exceptionCheck()
+{
+    // It's important that we use origin.forExit here. Consider if we hoist string
+    // addition outside a loop, and that we exit at the point of that concatenation
+    // from an out of memory exception.
+    // If the original loop had a try/catch around string concatenation, if we &quot;catch&quot;
+    // that exception inside the loop, then the loops induction variable will be undefined 
+    // in the OSR exit value recovery. It's more defensible for the string concatenation, 
+    // then, to not be caught by the for loops' try/catch.
+    // Here is the program I'm speaking about:
+    //
+    // &gt;&gt;&gt;&gt; lets presume &quot;c = a + b&quot; gets hoisted here.
+    // for (var i = 0; i &lt; length; i++) {
+    //     try {
+    //         c = a + b
+    //     } catch(e) { 
+    //         If we threw an out of memory error, and we cought the exception
+    //         right here, then &quot;i&quot; would almost certainly be undefined, which
+    //         would make no sense.
+    //         ... 
+    //     }
+    // }
+    CodeOrigin opCatchOrigin;
+    HandlerInfo* exceptionHandler;
+    bool willCatchException = willCatchExceptionInMachineFrame(m_speculative-&gt;m_currentNode-&gt;origin.forExit, opCatchOrigin, exceptionHandler); 
+    if (willCatchException) {
+        unsigned streamIndex = m_speculative-&gt;m_outOfLineStreamIndex != UINT_MAX ? m_speculative-&gt;m_outOfLineStreamIndex : m_speculative-&gt;m_stream-&gt;size();
+        MacroAssembler::Jump hadException = emitNonPatchableExceptionCheck();
+        // We assume here that this is called after callOpeartion()/appendCall() is called.
+        appendExceptionHandlingOSRExit(streamIndex, opCatchOrigin, exceptionHandler, m_jitCode-&gt;common.lastCallSite(), hadException);
+    } else
+        m_exceptionChecks.append(emitExceptionCheck());
+}
+
+CallSiteIndex JITCompiler::recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(const CodeOrigin&amp; callSiteCodeOrigin, unsigned eventStreamIndex)
+{
+    CodeOrigin opCatchOrigin;
+    HandlerInfo* exceptionHandler;
+    bool willCatchException = willCatchExceptionInMachineFrame(callSiteCodeOrigin, opCatchOrigin, exceptionHandler);
+    CallSiteIndex callSite = addCallSite(callSiteCodeOrigin);
+    if (willCatchException)
+        appendExceptionHandlingOSRExit(eventStreamIndex, opCatchOrigin, exceptionHandler, callSite);
+    return callSite;
+}
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -38,6 +38,7 @@
</span><span class="cx"> #include &quot;DFGRegisterBank.h&quot;
</span><span class="cx"> #include &quot;FPRInfo.h&quot;
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><ins>+#include &quot;HandlerInfo.h&quot;
</ins><span class="cx"> #include &quot;JITCode.h&quot;
</span><span class="cx"> #include &quot;JITInlineCacheGenerator.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="lines">@@ -158,6 +159,11 @@
</span><span class="cx">     void emitStoreCodeOrigin(CodeOrigin codeOrigin)
</span><span class="cx">     {
</span><span class="cx">         CallSiteIndex callSite = addCallSite(codeOrigin);
</span><ins>+        emitStoreCallSiteIndex(callSite);
+    }
+
+    void emitStoreCallSiteIndex(CallSiteIndex callSite)
+    {
</ins><span class="cx">         store32(TrustedImm32(callSite.bits()), tagFor(static_cast&lt;VirtualRegister&gt;(JSStack::ArgumentCount)));
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -169,10 +175,7 @@
</span><span class="cx">         return functionCall;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void exceptionCheck()
-    {
-        m_exceptionChecks.append(emitExceptionCheck());
-    }
</del><ins>+    void exceptionCheck();
</ins><span class="cx"> 
</span><span class="cx">     void exceptionCheckWithCallFrameRollback()
</span><span class="cx">     {
</span><span class="lines">@@ -260,6 +263,8 @@
</span><span class="cx">     
</span><span class="cx">     Vector&lt;Label&gt;&amp; blockHeads() { return m_blockHeads; }
</span><span class="cx"> 
</span><ins>+    CallSiteIndex recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(const CodeOrigin&amp;, unsigned eventStreamIndex);
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class OSRExitJumpPlaceholder;
</span><span class="cx">     
</span><span class="lines">@@ -273,7 +278,10 @@
</span><span class="cx">     void compileExceptionHandlers();
</span><span class="cx">     void linkOSRExits();
</span><span class="cx">     void disassemble(LinkBuffer&amp;);
</span><del>-    
</del><ins>+
+    bool willCatchExceptionInMachineFrame(CodeOrigin, CodeOrigin&amp; opCatchOriginOut, HandlerInfo*&amp; catchHandlerOut);
+    void appendExceptionHandlingOSRExit(unsigned eventStreamIndex, CodeOrigin, HandlerInfo* exceptionHandler, CallSiteIndex, MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList());
+
</ins><span class="cx">     // The dataflow graph currently being generated.
</span><span class="cx">     Graph&amp; m_graph;
</span><span class="cx"> 
</span><span class="lines">@@ -311,6 +319,13 @@
</span><span class="cx">     SegmentedVector&lt;OSRExitCompilationInfo, 4&gt; m_exitCompilationInfo;
</span><span class="cx">     Vector&lt;Vector&lt;Label&gt;&gt; m_exitSiteLabels;
</span><span class="cx">     
</span><ins>+    struct ExceptionHandlingOSRExitInfo {
+        OSRExitCompilationInfo&amp; exitInfo;
+        HandlerInfo baselineExceptionHandler;
+        CallSiteIndex callSiteIndex;
+    };
+    Vector&lt;ExceptionHandlingOSRExitInfo&gt; m_exceptionHandlerOSRExitCallSites;
+    
</ins><span class="cx">     Call m_callArityFixup;
</span><span class="cx">     Label m_arityCheck;
</span><span class="cx">     std::unique_ptr&lt;SpeculativeJIT&gt; m_speculative;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLiveCatchVariablePreservationPhasecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,178 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGLiveCatchVariablePreservationPhase.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGBasicBlockInlines.h&quot;
+#include &quot;DFGGraph.h&quot;
+#include &quot;DFGInsertionSet.h&quot;
+#include &quot;DFGPhase.h&quot;
+#include &quot;FullBytecodeLiveness.h&quot;
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC { namespace DFG {
+
+class FlushLiveCatchVariablesInsertionPhase : public Phase {
+public:
+    FlushLiveCatchVariablesInsertionPhase(Graph&amp; graph)
+        : Phase(graph, &quot;live catch variable preservation phase&quot;)
+    {
+    }
+
+    bool run()
+    {
+        if (!m_graph.m_hasExceptionHandlers)
+            return true;
+
+        DFG_ASSERT(m_graph, nullptr, m_graph.m_form == LoadStore);
+
+        m_currentBlockLiveness.resize(m_graph.block(0)-&gt;variablesAtTail.numberOfLocals());
+
+        InsertionSet insertionSet(m_graph);
+        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+            handleBlock(block, insertionSet);
+            insertionSet.execute(block);
+        }
+
+        return true;
+    }
+
+    bool willCatchException(CodeOrigin origin)
+    {
+        unsigned bytecodeIndexToCheck = origin.bytecodeIndex;
+        m_currentBlockLiveness.clearAll();
+
+        while (1) {
+            InlineCallFrame* inlineCallFrame = origin.inlineCallFrame;
+            CodeBlock* codeBlock = m_graph.baselineCodeBlockFor(inlineCallFrame);
+            if (HandlerInfo* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeIndexToCheck)) {
+                unsigned catchBytecodeIndex = handler-&gt;target;
+                m_graph.forAllLocalsLiveInBytecode(CodeOrigin(catchBytecodeIndex, inlineCallFrame), [&amp;] (VirtualRegister operand) {
+                    m_currentBlockLiveness.set(operand.toLocal(), true); 
+                });
+                return true;
+            }
+
+            if (!inlineCallFrame)
+                return false;
+
+            bytecodeIndexToCheck = inlineCallFrame-&gt;caller.bytecodeIndex;
+            origin = inlineCallFrame-&gt;caller;
+        }
+    }
+
+    void handleBlock(BasicBlock* block, InsertionSet&amp; insertionSet)
+    {
+        // Because precise jump targets ensures that the start of a &quot;try&quot; block is its
+        // own basic block, we will never have two &quot;try&quot; statements in the same DFG
+        // basic block. Therefore, checking the first node in the block is sufficient 
+        // to checking if we're in a try block.
+        if (!willCatchException(block-&gt;at(0)-&gt;origin.semantic))
+            return;
+
+        Operands&lt;VariableAccessData*&gt; currentBlockAccessData(block-&gt;variablesAtTail.numberOfArguments(), block-&gt;variablesAtTail.numberOfLocals(), nullptr);
+        HashSet&lt;InlineCallFrame*&gt; seenInlineCallFrames;
+
+        {
+            for (unsigned i = 0; i &lt; block-&gt;size(); i++) {
+                Node* node = block-&gt;at(i);
+                bool isPrimordialSetArgument = node-&gt;op() == SetArgument &amp;&amp; node-&gt;local().isArgument() &amp;&amp; node == m_graph.m_arguments[node-&gt;local().toArgument()];
+                InlineCallFrame* inlineCallFrame = node-&gt;origin.semantic.inlineCallFrame;
+                if (inlineCallFrame)
+                    seenInlineCallFrames.add(inlineCallFrame);
+
+                if (node-&gt;op() == SetLocal || (node-&gt;op() == SetArgument &amp;&amp; !isPrimordialSetArgument)) {
+                    VirtualRegister operand = node-&gt;local();
+
+                    int stackOffset = inlineCallFrame ? inlineCallFrame-&gt;stackOffset : 0;
+                    if ((operand.isLocal() &amp;&amp; m_currentBlockLiveness.get(operand.toLocal()))
+                        || (operand.offset() == stackOffset + CallFrame::thisArgumentOffset())) {
+
+                        VariableAccessData* flushAccessData = currentBlockAccessData.operand(operand);
+                        if (!flushAccessData)
+                            flushAccessData = newVariableAccessData(operand);
+
+                        insertionSet.insertNode(i, SpecNone, 
+                            Flush, node-&gt;origin, OpInfo(flushAccessData));
+                    }
+                }
+
+                if (node-&gt;hasVariableAccessData(m_graph))
+                    currentBlockAccessData.operand(node-&gt;local()) = node-&gt;variableAccessData();
+            }
+        }
+
+        // Flush everything at the end of the block.
+        // FIXME: I think this will only be necessary if we have any successor
+        // blocks who aren't inside this &quot;try&quot; statement. If all our successor's
+        // are in this try statement, they will have Flushes for any live &quot;catch&quot;
+        // variables.
+        {
+            NodeOrigin origin = block-&gt;at(block-&gt;size() - 1)-&gt;origin;
+            auto insertFlushAtEnd = [&amp;] (VirtualRegister operand, bool alwaysFlush) {
+                if ((operand.isLocal() &amp;&amp; m_currentBlockLiveness.get(operand.toLocal())) 
+                    || operand.isArgument()
+                    || alwaysFlush) {
+                    VariableAccessData* accessData = currentBlockAccessData.operand(operand);
+                    if (!accessData)
+                        accessData = newVariableAccessData(operand);
+
+                    currentBlockAccessData.operand(operand) = accessData;
+
+                    insertionSet.insertNode(block-&gt;size(), SpecNone, 
+                        Flush, origin, OpInfo(accessData));
+                }
+            };
+            for (unsigned local = 0; local &lt; block-&gt;variablesAtTail.numberOfLocals(); local++)
+                insertFlushAtEnd(virtualRegisterForLocal(local), false);
+            for (InlineCallFrame* inlineCallFrame : seenInlineCallFrames)
+                insertFlushAtEnd(VirtualRegister(inlineCallFrame-&gt;stackOffset + CallFrame::thisArgumentOffset()), true);
+            insertFlushAtEnd(VirtualRegister(CallFrame::thisArgumentOffset()), true);
+        }
+    }
+
+    VariableAccessData* newVariableAccessData(VirtualRegister operand)
+    {
+        ASSERT(!operand.isConstant());
+        
+        m_graph.m_variableAccessData.append(VariableAccessData(operand));
+        return &amp;m_graph.m_variableAccessData.last();
+    }
+
+    FastBitVector m_currentBlockLiveness;
+};
+
+bool performLiveCatchVariablePreservationPhase(Graph&amp; graph)
+{
+    SamplingRegion samplingRegion(&quot;DFG Live Catch Variables Preservation Phase&quot;);
+    return runPhase&lt;FlushLiveCatchVariablesInsertionPhase&gt;(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLiveCatchVariablePreservationPhaseh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.h (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGLiveCatchVariablePreservationPhase.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,52 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGLiveCatchVariablePreservationPhase_h
+#define DFGLiveCatchVariablePreservationPhase_h
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// This phase ensures that we maintain liveness for locals
+// that are live in the &quot;catch&quot; block. Because a &quot;catch&quot;
+// block will not be in the control flow graph, we need to ensure
+// anything live inside the &quot;catch&quot; block in bytecode will maintain 
+// liveness inside the &quot;try&quot; block for an OSR exit from the &quot;try&quot; 
+// block into the &quot;catch&quot; block in the case of an exception being thrown.
+//
+// The mechanism currently used to demonstrate liveness to OSR exit
+// is ensuring all variables live in a &quot;catch&quot; are flushed to the
+// stack inside the &quot;try&quot; block.
+
+bool performLiveCatchVariablePreservationPhase(Graph&amp;);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGLiveCatchVariablePreservationPhase_h
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AssemblyHelpers.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><ins>+#include &quot;DFGMayExit.h&quot;
</ins><span class="cx"> #include &quot;DFGSpeculativeJIT.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -42,8 +43,15 @@
</span><span class="cx">     , m_patchableCodeOffset(0)
</span><span class="cx">     , m_recoveryIndex(recoveryIndex)
</span><span class="cx">     , m_streamIndex(streamIndex)
</span><ins>+    , m_willArriveAtOSRExitFromGenericUnwind(false)
+    , m_isExceptionHandler(false)
</ins><span class="cx"> {
</span><del>-    DFG_ASSERT(jit-&gt;m_jit.graph(), jit-&gt;m_currentNode, jit-&gt;m_origin.exitOK);
</del><ins>+    bool canExit = jit-&gt;m_origin.exitOK;
+    if (!canExit &amp;&amp; jit-&gt;m_currentNode) {
+        ExitMode exitMode = mayExit(jit-&gt;m_jit.graph(), jit-&gt;m_currentNode);
+        canExit = exitMode == ExitMode::Exits || exitMode == ExitMode::ExitsForExceptions;
+    }
+    DFG_ASSERT(jit-&gt;m_jit.graph(), jit-&gt;m_currentNode, canExit);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void OSRExit::setPatchableCodeOffset(MacroAssembler::PatchableJump check)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExith"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -93,13 +93,16 @@
</span><span class="cx">     unsigned m_patchableCodeOffset;
</span><span class="cx">     
</span><span class="cx">     unsigned m_recoveryIndex;
</span><del>-    
</del><ins>+
</ins><span class="cx">     void setPatchableCodeOffset(MacroAssembler::PatchableJump);
</span><span class="cx">     MacroAssembler::Jump getPatchableCodeOffsetAsJump() const;
</span><span class="cx">     CodeLocationJump codeLocationForRepatch(CodeBlock*) const;
</span><span class="cx">     void correctJump(LinkBuffer&amp;);
</span><span class="cx"> 
</span><span class="cx">     unsigned m_streamIndex;
</span><ins>+
+    bool m_willArriveAtOSRExitFromGenericUnwind : 1;
+    bool m_isExceptionHandler : 1;
</ins><span class="cx">     
</span><span class="cx">     void considerAddingAsFrequentExitSite(CodeBlock* profiledCodeBlock)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -115,10 +115,9 @@
</span><span class="cx">     SamplingRegion samplingRegion(&quot;DFG OSR Exit Compilation&quot;);
</span><span class="cx">     
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><del>-    
</del><span class="cx">     ASSERT(codeBlock);
</span><span class="cx">     ASSERT(codeBlock-&gt;jitType() == JITCode::DFGJIT);
</span><del>-    
</del><ins>+
</ins><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     
</span><span class="cx">     // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
</span><span class="lines">@@ -128,6 +127,12 @@
</span><span class="cx">     uint32_t exitIndex = vm-&gt;osrExitIndex;
</span><span class="cx">     OSRExit&amp; exit = codeBlock-&gt;jitCode()-&gt;dfg()-&gt;osrExit[exitIndex];
</span><span class="cx">     
</span><ins>+    if (vm-&gt;callFrameForCatch)
+        ASSERT(exit.m_willArriveAtOSRExitFromGenericUnwind);
+    if (exit.m_isExceptionHandler)
+        ASSERT(!!vm-&gt;exception());
+        
+    
</ins><span class="cx">     prepareCodeOriginForOSRExit(exec, exit.m_codeOrigin);
</span><span class="cx">     
</span><span class="cx">     // Compute the value recoveries.
</span><span class="lines">@@ -153,7 +158,7 @@
</span><span class="cx">                 exit.m_kind, exit.m_kind == UncountableInvalidation);
</span><span class="cx">             jit.add64(CCallHelpers::TrustedImm32(1), CCallHelpers::AbsoluteAddress(profilerExit-&gt;counterAddress()));
</span><span class="cx">         }
</span><del>-        
</del><ins>+
</ins><span class="cx">         exitCompiler.compileExit(exit, operands, recovery);
</span><span class="cx">         
</span><span class="cx">         LinkBuffer patchBuffer(*vm, jit, codeBlock);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompiler32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -394,7 +394,7 @@
</span><span class="cx">     reifyInlinedCallFrames(m_jit, exit);
</span><span class="cx">     
</span><span class="cx">     // And finish.
</span><del>-    adjustAndJumpToTarget(m_jit, exit);
</del><ins>+    adjustAndJumpToTarget(m_jit, exit, exit.m_isExceptionHandler);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompiler64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -245,7 +245,7 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // Need to ensure that the stack pointer accounts for the worst-case stack usage at exit. This
</span><span class="cx">     // could toast some stack that the DFG used. We need to do it before storing to stack offsets
</span><span class="cx">     // used by baseline.
</span><span class="lines">@@ -384,7 +384,7 @@
</span><span class="cx">     reifyInlinedCallFrames(m_jit, exit);
</span><span class="cx"> 
</span><span class="cx">     // And finish.
</span><del>-    adjustAndJumpToTarget(m_jit, exit);
</del><ins>+    adjustAndJumpToTarget(m_jit, exit, exit.m_isExceptionHandler);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommoncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -248,7 +248,7 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(GGC)
</span><span class="cx"> 
</span><del>-void adjustAndJumpToTarget(CCallHelpers&amp; jit, const OSRExitBase&amp; exit)
</del><ins>+void adjustAndJumpToTarget(CCallHelpers&amp; jit, const OSRExitBase&amp; exit, bool isExitingToOpCatch)
</ins><span class="cx"> {
</span><span class="cx"> #if ENABLE(GGC) 
</span><span class="cx">     jit.move(AssemblyHelpers::TrustedImmPtr(jit.codeBlock()-&gt;ownerExecutable()), GPRInfo::argumentGPR1);
</span><span class="lines">@@ -277,6 +277,10 @@
</span><span class="cx">     void* jumpTarget = baselineCodeBlock-&gt;jitCode()-&gt;executableAddressAtOffset(mapping-&gt;m_machineCodeOffset);
</span><span class="cx"> 
</span><span class="cx">     jit.addPtr(AssemblyHelpers::TrustedImm32(JIT::stackPointerOffsetFor(baselineCodeBlock) * sizeof(Register)), GPRInfo::callFrameRegister, AssemblyHelpers::stackPointerRegister);
</span><ins>+    if (isExitingToOpCatch) {
+        // Since we're jumping to op_catch, we need to set callFrameForCatch.
+        jit.storePtr(GPRInfo::callFrameRegister, jit.vm()-&gt;addressOfCallFrameForCatch());
+    }
</ins><span class="cx">     
</span><span class="cx">     jit.move(AssemblyHelpers::TrustedImmPtr(jumpTarget), GPRInfo::regT2);
</span><span class="cx">     jit.jump(GPRInfo::regT2);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompilerCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> void handleExitCounts(CCallHelpers&amp;, const OSRExitBase&amp;);
</span><span class="cx"> void reifyInlinedCallFrames(CCallHelpers&amp;, const OSRExitBase&amp;);
</span><del>-void adjustAndJumpToTarget(CCallHelpers&amp;, const OSRExitBase&amp;);
</del><ins>+void adjustAndJumpToTarget(CCallHelpers&amp;, const OSRExitBase&amp;, bool isExitingToOpCatch);
</ins><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> #include &quot;DFGInvalidationPointInjectionPhase.h&quot;
</span><span class="cx"> #include &quot;DFGJITCompiler.h&quot;
</span><span class="cx"> #include &quot;DFGLICMPhase.h&quot;
</span><ins>+#include &quot;DFGLiveCatchVariablePreservationPhase.h&quot;
</ins><span class="cx"> #include &quot;DFGLivenessAnalysisPhase.h&quot;
</span><span class="cx"> #include &quot;DFGLoopPreHeaderCreationPhase.h&quot;
</span><span class="cx"> #include &quot;DFGMaximalFlushInsertionPhase.h&quot;
</span><span class="lines">@@ -259,6 +260,8 @@
</span><span class="cx">         dfg.dump();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    performLiveCatchVariablePreservationPhase(dfg);
+
</ins><span class="cx">     if (Options::enableMaximalFlushInsertionPhase())
</span><span class="cx">         performMaximalFlushInsertion(dfg);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSlowPathGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGSlowPathGenerator.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -40,6 +40,8 @@
</span><span class="cx"> public:
</span><span class="cx">     SlowPathGenerator(SpeculativeJIT* jit)
</span><span class="cx">         : m_currentNode(jit-&gt;m_currentNode)
</span><ins>+        , m_streamIndex(jit-&gt;m_stream-&gt;size())
+        , m_origin(jit-&gt;m_origin) 
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     virtual ~SlowPathGenerator() { }
</span><span class="lines">@@ -47,7 +49,10 @@
</span><span class="cx">     {
</span><span class="cx">         m_label = jit-&gt;m_jit.label();
</span><span class="cx">         jit-&gt;m_currentNode = m_currentNode;
</span><ins>+        jit-&gt;m_outOfLineStreamIndex = m_streamIndex;
+        jit-&gt;m_origin = m_origin;
</ins><span class="cx">         generateInternal(jit);
</span><ins>+        jit-&gt;m_outOfLineStreamIndex = UINT_MAX;
</ins><span class="cx">         if (!ASSERT_DISABLED)
</span><span class="cx">             jit-&gt;m_jit.abortWithReason(DFGSlowPathGeneratorFellThrough);
</span><span class="cx">     }
</span><span class="lines">@@ -61,6 +66,8 @@
</span><span class="cx">     virtual void generateInternal(SpeculativeJIT*) = 0;
</span><span class="cx">     MacroAssembler::Label m_label;
</span><span class="cx">     Node* m_currentNode;
</span><ins>+    unsigned m_streamIndex;
+    NodeOrigin m_origin;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename JumpType&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -2476,6 +2476,7 @@
</span><span class="cx">     
</span><span class="cx">     Vector&lt;std::unique_ptr&lt;SlowPathGenerator&gt;, 8&gt; m_slowPathGenerators;
</span><span class="cx">     Vector&lt;SilentRegisterSavePlan&gt; m_plans;
</span><ins>+    unsigned m_outOfLineStreamIndex { UINT_MAX };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -182,8 +182,9 @@
</span><span class="cx">         basePayloadGPR = resultPayloadGPR;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
</ins><span class="cx">     JITGetByIdGenerator gen(
</span><del>-        m_jit.codeBlock(), codeOrigin, m_jit.addCallSite(codeOrigin), usedRegisters(),
</del><ins>+        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters(),
</ins><span class="cx">         JSValueRegs(baseTagGPROrNone, basePayloadGPR),
</span><span class="cx">         JSValueRegs(resultTagGPR, resultPayloadGPR), spillMode);
</span><span class="cx">     
</span><span class="lines">@@ -214,8 +215,9 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><ins>+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
</ins><span class="cx">     JITPutByIdGenerator gen(
</span><del>-        m_jit.codeBlock(), codeOrigin, m_jit.addCallSite(codeOrigin), usedRegisters(),
</del><ins>+        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters(),
</ins><span class="cx">         JSValueRegs::payloadOnly(basePayloadGPR), JSValueRegs(valueTagGPR, valuePayloadGPR),
</span><span class="cx">         scratchGPR, spillMode, m_jit.ecmaModeFor(codeOrigin), putKind);
</span><span class="cx">     
</span><span class="lines">@@ -784,7 +786,8 @@
</span><span class="cx">     JITCompiler::DataLabelPtr targetToCheck;
</span><span class="cx">     JITCompiler::JumpList slowPath;
</span><span class="cx"> 
</span><del>-    m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</del><ins>+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(node-&gt;origin.semantic, m_stream-&gt;size());
+    m_jit.emitStoreCallSiteIndex(callSite);
</ins><span class="cx">     
</span><span class="cx">     CallLinkInfo* info = m_jit.codeBlock()-&gt;addCallLinkInfo();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -153,8 +153,10 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><ins>+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
+
</ins><span class="cx">     JITGetByIdGenerator gen(
</span><del>-        m_jit.codeBlock(), codeOrigin, m_jit.addCallSite(codeOrigin), usedRegisters(), JSValueRegs(baseGPR),
</del><ins>+        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters(), JSValueRegs(baseGPR),
</ins><span class="cx">         JSValueRegs(resultGPR), spillMode);
</span><span class="cx">     gen.generateFastPath(m_jit);
</span><span class="cx">     
</span><span class="lines">@@ -173,8 +175,10 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><ins>+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream-&gt;size());
+
</ins><span class="cx">     JITPutByIdGenerator gen(
</span><del>-        m_jit.codeBlock(), codeOrigin, m_jit.addCallSite(codeOrigin), usedRegisters(), JSValueRegs(baseGPR),
</del><ins>+        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters(), JSValueRegs(baseGPR),
</ins><span class="cx">         JSValueRegs(valueGPR), scratchGPR, spillMode, m_jit.ecmaModeFor(codeOrigin), putKind);
</span><span class="cx"> 
</span><span class="cx">     gen.generateFastPath(m_jit);
</span><span class="lines">@@ -752,7 +756,8 @@
</span><span class="cx">     JITCompiler::DataLabelPtr targetToCheck;
</span><span class="cx">     JITCompiler::Jump slowPath;
</span><span class="cx"> 
</span><del>-    m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</del><ins>+    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(node-&gt;origin.semantic, m_stream-&gt;size());
+    m_jit.emitStoreCallSiteIndex(callSite);
</ins><span class="cx">     
</span><span class="cx">     CallLinkInfo* callLinkInfo = m_jit.codeBlock()-&gt;addCallLinkInfo();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -52,6 +52,9 @@
</span><span class="cx">         
</span><span class="cx">         if (m_graph.m_profiledBlock-&gt;m_didFailFTLCompilation)
</span><span class="cx">             return false;
</span><ins>+
+        if (m_graph.m_hasExceptionHandlers)
+            return false;
</ins><span class="cx">         
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx">         FTL::CapabilityLevel level = FTL::canCompile(m_graph);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -516,7 +516,7 @@
</span><span class="cx">     
</span><span class="cx">     handleExitCounts(jit, exit);
</span><span class="cx">     reifyInlinedCallFrames(jit, exit);
</span><del>-    adjustAndJumpToTarget(jit, exit);
</del><ins>+    adjustAndJumpToTarget(jit, exit, false);
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, codeBlock);
</span><span class="cx">     exit.m_code = FINALIZE_CODE_IF(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -614,12 +614,19 @@
</span><span class="cx"> 
</span><span class="cx">     StackVisitor::Status operator()(StackVisitor&amp; visitor)
</span><span class="cx">     {
</span><ins>+        visitor.unwindToMachineCodeBlockFrame();
+
</ins><span class="cx">         CodeBlock* codeBlock = visitor-&gt;codeBlock();
</span><span class="cx">         if (!codeBlock)
</span><span class="cx">             return StackVisitor::Continue;
</span><span class="cx"> 
</span><del>-        unsigned bytecodeOffset = visitor-&gt;bytecodeOffset();
-        m_handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset, CodeBlock::RequiredHandler::CatchHandler);
</del><ins>+        unsigned exceptionHandlerIndex;
+        if (codeBlock-&gt;jitType() != JITCode::DFGJIT)
+            exceptionHandlerIndex = visitor-&gt;callFrame()-&gt;bytecodeOffset();
+        else
+            exceptionHandlerIndex = visitor-&gt;callFrame()-&gt;callSiteIndex().bits();
+
+        m_handler = codeBlock-&gt;handlerForIndex(exceptionHandlerIndex, CodeBlock::RequiredHandler::CatchHandler);
</ins><span class="cx">         if (m_handler)
</span><span class="cx">             return StackVisitor::Done;
</span><span class="cx"> 
</span><span class="lines">@@ -642,15 +649,20 @@
</span><span class="cx"> 
</span><span class="cx">     StackVisitor::Status operator()(StackVisitor&amp; visitor)
</span><span class="cx">     {
</span><ins>+        visitor.unwindToMachineCodeBlockFrame();
</ins><span class="cx">         VM&amp; vm = m_callFrame-&gt;vm();
</span><span class="cx">         m_callFrame = visitor-&gt;callFrame();
</span><span class="cx">         m_codeBlock = visitor-&gt;codeBlock();
</span><del>-        unsigned bytecodeOffset = visitor-&gt;bytecodeOffset();
</del><span class="cx"> 
</span><ins>+        unsigned exceptionHandlerIndex;
+        if (m_codeBlock-&gt;jitType() != JITCode::DFGJIT)
+            exceptionHandlerIndex = m_callFrame-&gt;bytecodeOffset();
+        else
+            exceptionHandlerIndex = m_callFrame-&gt;callSiteIndex().bits();
</ins><span class="cx">         m_handler = nullptr;
</span><span class="cx">         if (!m_isTermination) {
</span><span class="cx">             if (m_codeBlock &amp;&amp; !isWebAssemblyExecutable(m_codeBlock-&gt;ownerExecutable()))
</span><del>-                m_handler = m_codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset);
</del><ins>+                m_handler = m_codeBlock-&gt;handlerForIndex(exceptionHandlerIndex);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_handler)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -69,6 +69,14 @@
</span><span class="cx">     readFrame(m_frame.callerFrame());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+CodeBlock* StackVisitor::unwindToMachineCodeBlockFrame()
+{
+    while (m_frame.isInlinedFrame())
+        gotoNextFrame();
+    CodeBlock* result = m_frame.codeBlock();
+    return result;
+}
+
</ins><span class="cx"> void StackVisitor::readFrame(CallFrame* callFrame)
</span><span class="cx"> {
</span><span class="cx">     if (!callFrame) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -131,6 +131,7 @@
</span><span class="cx"> 
</span><span class="cx">     Frame&amp; operator*() { return m_frame; }
</span><span class="cx">     ALWAYS_INLINE Frame* operator-&gt;() { return &amp;m_frame; }
</span><ins>+    CodeBlock* unwindToMachineCodeBlockFrame();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     JS_EXPORT_PRIVATE StackVisitor(CallFrame* startFrame);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -273,6 +273,20 @@
</span><span class="cx">     return realJump.m_jump;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AssemblyHelpers::Jump AssemblyHelpers::emitNonPatchableExceptionCheck()
+{
+    callExceptionFuzz();
+
+    Jump result;
+#if USE(JSVALUE64)
+    result = branchTest64(NonZero, AbsoluteAddress(vm()-&gt;addressOfException()));
+#elif USE(JSVALUE32_64)
+    result = branch32(NotEqual, AbsoluteAddress(vm()-&gt;addressOfException()), TrustedImm32(0));
+#endif
+    
+    return result;
+}
+
</ins><span class="cx"> void AssemblyHelpers::emitStoreStructureWithTypeInfo(AssemblyHelpers&amp; jit, TrustedImmPtr structure, RegisterID dest)
</span><span class="cx"> {
</span><span class="cx">     const Structure* structurePtr = static_cast&lt;const Structure*&gt;(structure.m_value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -1021,6 +1021,7 @@
</span><span class="cx">     enum ExceptionJumpWidth { NormalJumpWidth, FarJumpWidth };
</span><span class="cx">     Jump emitExceptionCheck(
</span><span class="cx">         ExceptionCheckKind = NormalExceptionCheck, ExceptionJumpWidth = NormalJumpWidth);
</span><ins>+    Jump emitNonPatchableExceptionCheck();
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(SAMPLING_COUNTERS)
</span><span class="cx">     static void emitCount(MacroAssembler&amp; jit, AbstractSamplingCounter&amp; counter, int32_t increment = 1)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITExceptionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITExceptions.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITExceptions.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/jit/JITExceptions.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -54,7 +54,14 @@
</span><span class="cx">     void* catchRoutine;
</span><span class="cx">     Instruction* catchPCForInterpreter = 0;
</span><span class="cx">     if (handler) {
</span><del>-        catchPCForInterpreter = &amp;callFrame-&gt;codeBlock()-&gt;instructions()[handler-&gt;target];
</del><ins>+        // handler-&gt;target is meaningless for getting a code offset when catching
+        // the exception in a DFG frame. This bytecode target offset could be
+        // something that's in an inlined frame, which means an array access
+        // with this bytecode offset in the machine frame is utterly meaningless
+        // and can cause an overflow. OSR exit properly exits to handler-&gt;target
+        // in the proper frame.
+        if (callFrame-&gt;codeBlock()-&gt;jitType() != JITCode::DFGJIT)
+            catchPCForInterpreter = &amp;callFrame-&gt;codeBlock()-&gt;instructions()[handler-&gt;target];
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">         catchRoutine = handler-&gt;nativeCode.executableAddress();
</span><span class="cx"> #else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -501,6 +501,7 @@
</span><span class="cx"> 
</span><span class="cx">     move(TrustedImmPtr(m_vm), regT3);
</span><span class="cx">     load64(Address(regT3, VM::callFrameForCatchOffset()), callFrameRegister);
</span><ins>+    storePtr(TrustedImmPtr(nullptr), Address(regT3, VM::callFrameForCatchOffset()));
</ins><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -807,6 +807,7 @@
</span><span class="cx">     move(TrustedImmPtr(m_vm), regT3);
</span><span class="cx">     // operationThrow returns the callFrame for the handler.
</span><span class="cx">     load32(Address(regT3, VM::callFrameForCatchOffset()), callFrameRegister);
</span><ins>+    storePtr(TrustedImmPtr(nullptr), Address(regT3, VM::callFrameForCatchOffset()));
</ins><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -304,6 +304,7 @@
</span><span class="cx">     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
</span><span class="cx">     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
</span><span class="cx">     loadp VM::callFrameForCatch[t3], cfr
</span><ins>+    storep 0, VM::callFrameForCatch[t3]
</ins><span class="cx"> 
</span><span class="cx">     loadp CallerFrame[cfr], cfr
</span><span class="cx"> 
</span><span class="lines">@@ -1837,6 +1838,7 @@
</span><span class="cx">     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
</span><span class="cx">     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
</span><span class="cx">     loadp VM::callFrameForCatch[t3], cfr
</span><ins>+    storep 0, VM::callFrameForCatch[t3]
</ins><span class="cx">     restoreStackPointerAfterCall()
</span><span class="cx"> 
</span><span class="cx">     loadi VM::targetInterpreterPCForThrow[t3], PC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -276,6 +276,7 @@
</span><span class="cx">     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
</span><span class="cx">     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
</span><span class="cx">     loadp VM::callFrameForCatch[t3], cfr
</span><ins>+    storep 0, VM::callFrameForCatch[t3]
</ins><span class="cx"> 
</span><span class="cx">     loadp CallerFrame[cfr], cfr
</span><span class="cx">     vmEntryRecord(cfr, t2)
</span><span class="lines">@@ -1723,6 +1724,7 @@
</span><span class="cx">     loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
</span><span class="cx">     restoreCalleeSavesFromVMCalleeSavesBuffer(t3, t0)
</span><span class="cx">     loadp VM::callFrameForCatch[t3], cfr
</span><ins>+    storep 0, VM::callFrameForCatch[t3]
</ins><span class="cx">     restoreStackPointerAfterCall()
</span><span class="cx"> 
</span><span class="cx">     loadp CodeBlock[cfr], PB
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (189937 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-09-17 22:02:49 UTC (rev 189937)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -407,6 +407,8 @@
</span><span class="cx">     void clearException() { m_exception = nullptr; }
</span><span class="cx">     void clearLastException() { m_lastException = nullptr; }
</span><span class="cx"> 
</span><ins>+    ExecState** addressOfCallFrameForCatch() { return &amp;callFrameForCatch; }
+
</ins><span class="cx">     Exception* exception() const { return m_exception; }
</span><span class="cx">     JSCell** addressOfException() { return reinterpret_cast&lt;JSCell**&gt;(&amp;m_exception); }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdfgexceptiontrycatchinconstructorwithinlinedthrowjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/dfg-exception-try-catch-in-constructor-with-inlined-throw.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/dfg-exception-try-catch-in-constructor-with-inlined-throw.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/dfg-exception-try-catch-in-constructor-with-inlined-throw.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,27 @@
</span><ins>+function f() {
+    return 20; 
+}
+noInline(f);
+
+function bar(b) { 
+    if (b)
+        throw new Error(&quot;blah!&quot;);
+}
+
+function Foo(b) {
+    try {
+        this.value = bar(b);
+    } catch(e) {
+        this.value = e.toString();
+    }
+
+    f(this.value, b);
+}
+noInline(Foo);
+
+
+for (var i = 1; i &lt; 1000; i++) {
+    let value = new Foo(i % 3 === 0);
+    if (i % 3 === 0 &amp;&amp; value.value !==  &quot;Error: blah!&quot;)
+        throw new Error(&quot;bad value: &quot; + value.value);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresses6forofloopexceptionjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/es6-for-of-loop-exception.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/es6-for-of-loop-exception.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/es6-for-of-loop-exception.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+function assert(cond) {
+    if (!cond)
+        throw new Error(&quot;broke assertion&quot;);
+}
+noInline(assert);
+
+function shouldThrowInvalidConstAssignment(f) {
+    var threw = false;
+    try {
+        f();
+    } catch(e) {
+        //print(e);
+        if (e.name.indexOf(&quot;TypeError&quot;) !== -1 &amp;&amp; e.message.indexOf(&quot;readonly&quot;) !== -1)
+            threw = true;
+    }
+    assert(threw);
+}
+noInline(shouldThrowInvalidConstAssignment);
+
+function baz(){}
+noInline(baz);
+
+function foo() {
+    for (const item of [1,2,3]) {
+        item = 20;
+    }
+}
+for (var i = 0; i &lt; 1000; i++)
+    shouldThrowInvalidConstAssignment(foo);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressexceptiondfginlinedframenotstrictequaljs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/exception-dfg-inlined-frame-not-strict-equal.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/exception-dfg-inlined-frame-not-strict-equal.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/exception-dfg-inlined-frame-not-strict-equal.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,39 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;);
+}
+noInline(assert);
+var o = {
+    valueOf: function() { return {}; },
+    toString: function() { return {}; }
+};
+function read() {
+    return &quot;read&quot;;
+}
+noInline(read);
+
+function bar(a, b) {
+    return a == b;
+}
+
+function foo(a, b) {
+    var result = null;
+    var value = read();
+    try {
+        result = bar(a, b);
+    } catch(e) {
+        assert(&quot;&quot; + value === &quot;read&quot;);
+    }
+    return value;
+}
+noInline(foo);
+
+for (var i = 0; i &lt; 1000; i++) {
+    foo(10, 20);
+    foo({}, {});
+    foo(10, 10.0);
+    foo(&quot;hello&quot;, &quot;hello&quot;);
+    foo(null, undefined);
+    foo(false, 0);
+}
+foo(o, &quot;hello&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressexceptiondfgnotstrictequaljs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/exception-dfg-not-strict-equal.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/exception-dfg-not-strict-equal.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/exception-dfg-not-strict-equal.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,71 @@
</span><ins>+;(function () {
+function foo(a, b) {
+    var result = null;
+    try {
+        result = a == b;
+    } catch(e) {
+    }
+}
+noInline(foo);
+
+for (var i = 0; i &lt; 1000; i++) {
+    foo(10, 20);
+    foo({}, {});
+    foo(10, 10.0);
+    foo(&quot;hello&quot;, &quot;hello&quot;);
+    foo(null, undefined);
+    foo(false, 0);
+}
+
+var o = {
+    valueOf: function() { return {}; },
+    toString: function() { return {}; }
+};
+foo(o, &quot;hello&quot;);
+})();
+
+
+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;);
+}
+noInline(assert);
+
+
+;(function() {
+
+var _shouldDoSomethingInFinally = false;
+function shouldDoSomethingInFinally() { return _shouldDoSomethingInFinally; }
+noInline(shouldDoSomethingInFinally);
+
+function foo(a, b) {
+    var result = null;
+    try {
+        result = a == b;
+    } finally {
+        if (shouldDoSomethingInFinally())
+            assert(result === null);
+    }
+    return result;
+}
+noInline(foo);
+
+for (var i = 0; i &lt; 1000; i++) {
+    foo(10, 20);
+    foo({}, {});
+    foo(10, 10.0);
+    foo(&quot;hello&quot;, &quot;hello&quot;);
+    foo(null, undefined);
+    foo(false, 0);
+}
+
+var o = {
+    valueOf: function() { return {}; },
+    toString: function() { return {}; }
+};
+try {
+    _shouldDoSomethingInFinally = true;
+    foo(o, &quot;hello&quot;);
+} catch(e) {}
+
+})();
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressexceptiondfgoperationreadvaluejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/exception-dfg-operation-read-value.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/exception-dfg-operation-read-value.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/exception-dfg-operation-read-value.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+function assert(b) {
+    if (!b)
+        throw new Error(&quot;Bad assertion&quot;);
+}
+noInline(assert);
+var o = {
+    valueOf: function() { return {}; },
+    toString: function() { return {}; }
+};
+function read() {
+    return &quot;read&quot;;
+}
+noInline(read);
+
+function foo(a, b) {
+    var result = null;
+    var value = read();
+    try {
+        result = a == b;
+    } catch(e) {
+        assert(&quot;&quot; + value === &quot;read&quot;);
+    }
+    return value;
+}
+noInline(foo);
+
+for (var i = 0; i &lt; 1000; i++) {
+    foo(10, 20);
+    foo({}, {});
+    foo(10, 10.0);
+    foo(&quot;hello&quot;, &quot;hello&quot;);
+    foo(null, undefined);
+    foo(false, 0);
+}
+foo(o, &quot;hello&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressexceptiondfgthrowfromcatchblockjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/exception-dfg-throw-from-catch-block.js (0 => 189938)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/exception-dfg-throw-from-catch-block.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/exception-dfg-throw-from-catch-block.js        2015-09-17 22:02:54 UTC (rev 189938)
</span><span class="lines">@@ -0,0 +1,40 @@
</span><ins>+&quot;use strict&quot;;
+function assert(cond, m) {
+    if (!cond)
+        throw new Error(&quot;broke assertion: '&quot; + m + &quot;'&quot;);
+}
+noInline(assert);
+
+function baz(b) {
+    if (b)
+        throw new Error(&quot;Baz&quot;);
+}
+
+function bar(b) {
+    var exception = null;
+    try {
+        baz(b);
+    } catch(e) {
+        exception = e;
+        baz(b);
+    } finally {
+        if (b) 
+            assert(exception);
+    }
+}
+
+function foo(b) {
+    var exception = null;
+    try {
+        bar(b);
+    } catch(e) {
+        exception = e;
+    }
+    if (b)
+        assert(exception);
+}
+
+const NUM_LOOPS = 1000;
+for (var i = 0; i &lt; NUM_LOOPS; i++) {
+    foo(i === NUM_LOOPS - 1);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>