summaryrefslogtreecommitdiffstats
path: root/js/src/jit/JitFrames.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/JitFrames.cpp')
-rw-r--r--js/src/jit/JitFrames.cpp99
1 files changed, 83 insertions, 16 deletions
diff --git a/js/src/jit/JitFrames.cpp b/js/src/jit/JitFrames.cpp
index 646442b4c..966d952d3 100644
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -328,23 +328,46 @@ NumArgAndLocalSlots(const InlineFrameIterator& frame)
}
static void
-CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, uint32_t stackSlot)
+CloseLiveIteratorIon(JSContext* cx, const InlineFrameIterator& frame, JSTryNote* tn)
{
+ MOZ_ASSERT(tn->kind == JSTRY_FOR_IN ||
+ tn->kind == JSTRY_DESTRUCTURING_ITERCLOSE);
+
+ bool isDestructuring = tn->kind == JSTRY_DESTRUCTURING_ITERCLOSE;
+ MOZ_ASSERT_IF(!isDestructuring, tn->stackDepth > 0);
+ MOZ_ASSERT_IF(isDestructuring, tn->stackDepth > 1);
+
SnapshotIterator si = frame.snapshotIterator();
- // Skip stack slots until we reach the iterator object.
- uint32_t skipSlots = NumArgAndLocalSlots(frame) + stackSlot - 1;
+ // Skip stack slots until we reach the iterator object on the stack. For
+ // the destructuring case, we also need to get the "done" value.
+ uint32_t stackSlot = tn->stackDepth;
+ uint32_t adjust = isDestructuring ? 2 : 1;
+ uint32_t skipSlots = NumArgAndLocalSlots(frame) + stackSlot - adjust;
for (unsigned i = 0; i < skipSlots; i++)
si.skip();
Value v = si.read();
- RootedObject obj(cx, &v.toObject());
+ RootedObject iterObject(cx, &v.toObject());
+
+ if (isDestructuring) {
+ RootedValue doneValue(cx, si.read());
+ bool done = ToBoolean(doneValue);
+ // Do not call IteratorClose if the destructuring iterator is already
+ // done.
+ if (done)
+ return;
+ }
- if (cx->isExceptionPending())
- UnwindIteratorForException(cx, obj);
- else
- UnwindIteratorForUncatchableException(cx, obj);
+ if (cx->isExceptionPending()) {
+ if (tn->kind == JSTRY_FOR_IN)
+ UnwindIteratorForException(cx, iterObject);
+ else
+ IteratorCloseForException(cx, iterObject);
+ } else {
+ UnwindIteratorForUncatchableException(cx, iterObject);
+ }
}
class IonFrameStackDepthOp
@@ -413,25 +436,36 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
if (!script->hasTrynotes())
return;
+ bool inForOfIterClose = false;
+
for (TryNoteIterIon tni(cx, frame); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
switch (tn->kind) {
- case JSTRY_FOR_IN: {
- MOZ_ASSERT(JSOp(*(script->main() + tn->start + tn->length)) == JSOP_ENDITER);
- MOZ_ASSERT(tn->stackDepth > 0);
+ case JSTRY_FOR_IN:
+ case JSTRY_DESTRUCTURING_ITERCLOSE:
+ MOZ_ASSERT_IF(tn->kind == JSTRY_FOR_IN,
+ JSOp(*(script->main() + tn->start + tn->length)) == JSOP_ENDITER);
+ CloseLiveIteratorIon(cx, frame, tn);
+ break;
- uint32_t localSlot = tn->stackDepth;
- CloseLiveIteratorIon(cx, frame, localSlot);
+ case JSTRY_FOR_OF_ITERCLOSE:
+ inForOfIterClose = true;
break;
- }
case JSTRY_FOR_OF:
+ inForOfIterClose = false;
+ break;
+
case JSTRY_LOOP:
break;
case JSTRY_CATCH:
if (cx->isExceptionPending()) {
+ // See corresponding comment in ProcessTryNotes.
+ if (inForOfIterClose)
+ break;
+
// Ion can compile try-catch, but bailing out to catch
// exceptions is slow. Reset the warm-up counter so that if we
// catch many exceptions we won't Ion-compile the script.
@@ -562,6 +596,7 @@ ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, Environmen
ResumeFromException* rfe, jsbytecode** pc)
{
RootedScript script(cx, frame.baselineFrame()->script());
+ bool inForOfIterClose = false;
for (TryNoteIterBaseline tni(cx, frame.baselineFrame(), *pc); !tni.done(); ++tni) {
JSTryNote* tn = *tni;
@@ -572,7 +607,11 @@ ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, Environmen
// If we're closing a legacy generator, we have to skip catch
// blocks.
if (cx->isClosingGenerator())
- continue;
+ break;
+
+ // See corresponding comment in ProcessTryNotes.
+ if (inForOfIterClose)
+ break;
SettleOnTryNote(cx, tn, frame, ei, rfe, pc);
@@ -588,6 +627,10 @@ ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, Environmen
}
case JSTRY_FINALLY: {
+ // See corresponding comment in ProcessTryNotes.
+ if (inForOfIterClose)
+ break;
+
SettleOnTryNote(cx, tn, frame, ei, rfe, pc);
rfe->kind = ResumeFromException::RESUME_FINALLY;
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc);
@@ -602,7 +645,7 @@ ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, Environmen
uint8_t* framePointer;
uint8_t* stackPointer;
BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer, &stackPointer);
- Value iterValue(*(Value*) stackPointer);
+ Value iterValue(*reinterpret_cast<Value*>(stackPointer));
RootedObject iterObject(cx, &iterValue.toObject());
if (!UnwindIteratorForException(cx, iterObject)) {
// See comment in the JSTRY_FOR_IN case in Interpreter.cpp's
@@ -614,7 +657,31 @@ ProcessTryNotesBaseline(JSContext* cx, const JitFrameIterator& frame, Environmen
break;
}
+ case JSTRY_DESTRUCTURING_ITERCLOSE: {
+ uint8_t* framePointer;
+ uint8_t* stackPointer;
+ BaselineFrameAndStackPointersFromTryNote(tn, frame, &framePointer, &stackPointer);
+ RootedValue doneValue(cx, *(reinterpret_cast<Value*>(stackPointer)));
+ bool done = ToBoolean(doneValue);
+ if (!done) {
+ Value iterValue(*(reinterpret_cast<Value*>(stackPointer) + 1));
+ RootedObject iterObject(cx, &iterValue.toObject());
+ if (!IteratorCloseForException(cx, iterObject)) {
+ SettleOnTryNote(cx, tn, frame, ei, rfe, pc);
+ return false;
+ }
+ }
+ break;
+ }
+
+ case JSTRY_FOR_OF_ITERCLOSE:
+ inForOfIterClose = true;
+ break;
+
case JSTRY_FOR_OF:
+ inForOfIterClose = false;
+ break;
+
case JSTRY_LOOP:
break;