diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-03 09:55:33 +0100 |
commit | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch) | |
tree | 8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp | |
parent | d11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff) | |
download | qtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz |
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp')
-rw-r--r-- | Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp | 236 |
1 files changed, 133 insertions, 103 deletions
diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index a0127d8d7..46ec698de 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -5,6 +5,7 @@ * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> + * Copyright (C) 2012 Igalia, S.L. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -146,14 +147,15 @@ bool ResolveNode::isPure(BytecodeGenerator& generator) const RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RegisterID* local = generator.registerFor(m_ident)) { + ResolveResult resolveResult = generator.resolve(m_ident); + if (RegisterID* local = resolveResult.local()) { if (dst == generator.ignoredResult()) return 0; return generator.moveToDestinationIfNeeded(dst, local); } generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0); - return generator.emitResolve(generator.finalDestination(dst), m_ident); + return generator.emitResolve(generator.finalDestination(dst), resolveResult, m_ident); } // ------------------------------ ArrayNode ------------------------------------ @@ -236,27 +238,79 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe generator.emitNewObject(newObj.get()); - for (PropertyListNode* p = this; p; p = p->m_next) { - RegisterID* value = generator.emitNode(p->m_node->m_assign); - - switch (p->m_node->m_type) { - case PropertyNode::Constant: { - generator.emitDirectPutById(newObj.get(), p->m_node->name(), value); - break; - } - case PropertyNode::Getter: { - generator.emitPutGetter(newObj.get(), p->m_node->name(), value); - break; + // Fast case: this loop just handles regular value properties. + PropertyListNode* p = this; + for (; p && p->m_node->m_type == PropertyNode::Constant; p = p->m_next) + generator.emitDirectPutById(newObj.get(), p->m_node->name(), generator.emitNode(p->m_node->m_assign)); + + // Were there any get/set properties? + if (p) { + typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair; + typedef HashMap<StringImpl*, GetterSetterPair> GetterSetterMap; + GetterSetterMap map; + + // Build a map, pairing get/set values together. + for (PropertyListNode* q = p; q; q = q->m_next) { + PropertyNode* node = q->m_node; + if (node->m_type == PropertyNode::Constant) + continue; + + GetterSetterPair pair(node, 0); + std::pair<GetterSetterMap::iterator, bool> result = map.add(node->name().impl(), pair); + if (!result.second) + result.first->second.second = node; + } + + // Iterate over the remaining properties in the list. + for (; p; p = p->m_next) { + PropertyNode* node = p->m_node; + RegisterID* value = generator.emitNode(node->m_assign); + + // Handle regular values. + if (node->m_type == PropertyNode::Constant) { + generator.emitDirectPutById(newObj.get(), node->name(), value); + continue; } - case PropertyNode::Setter: { - generator.emitPutSetter(newObj.get(), p->m_node->name(), value); - break; + + // This is a get/set property, find its entry in the map. + ASSERT(node->m_type == PropertyNode::Getter || node->m_type == PropertyNode::Setter); + GetterSetterMap::iterator it = map.find(node->name().impl()); + ASSERT(it != map.end()); + GetterSetterPair& pair = it->second; + + // Was this already generated as a part of its partner? + if (pair.second == node) + continue; + + // Generate the paired node now. + RefPtr<RegisterID> getterReg; + RefPtr<RegisterID> setterReg; + + if (node->m_type == PropertyNode::Getter) { + getterReg = value; + if (pair.second) { + ASSERT(pair.second->m_type == PropertyNode::Setter); + setterReg = generator.emitNode(pair.second->m_assign); + } else { + setterReg = generator.newTemporary(); + generator.emitLoad(setterReg.get(), jsUndefined()); + } + } else { + ASSERT(node->m_type == PropertyNode::Setter); + setterReg = value; + if (pair.second) { + ASSERT(pair.second->m_type == PropertyNode::Getter); + getterReg = generator.emitNode(pair.second->m_assign); + } else { + getterReg = generator.newTemporary(); + generator.emitLoad(getterReg.get(), jsUndefined()); + } } - default: - ASSERT_NOT_REACHED(); + + generator.emitPutGetterSetter(newObj.get(), node->name(), getterReg.get(), setterReg.get()); } } - + return generator.moveToDestinationIfNeeded(dst, newObj.get()); } @@ -346,7 +400,7 @@ RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, Reg RefPtr<RegisterID> func = generator.tempDestination(dst); CallArguments callArguments(generator, m_args); generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); - generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.propertyNames().eval); + generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.resolve(generator.propertyNames().eval), generator.propertyNames().eval); return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } @@ -364,19 +418,19 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { + ResolveResult resolveResult = generator.resolve(m_ident); + + if (RegisterID* local = resolveResult.local()) { + RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local); CallArguments callArguments(generator, m_args); generator.emitLoad(callArguments.thisRegister(), jsUndefined()); - return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), local.get(), callArguments, divot(), startOffset(), endOffset()); + return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), callArguments, divot(), startOffset(), endOffset()); } - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - bool requiresDynamicChecks = false; - if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { - RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); + if (resolveResult.isStatic()) { + RefPtr<RegisterID> func = generator.newTemporary(); CallArguments callArguments(generator, m_args); + generator.emitGetStaticVar(func.get(), resolveResult); generator.emitLoad(callArguments.thisRegister(), jsUndefined()); return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } @@ -384,8 +438,9 @@ RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RefPtr<RegisterID> func = generator.newTemporary(); CallArguments callArguments(generator, m_args); int identifierStart = divot() - startOffset(); + generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0); - generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), m_ident); + generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident); return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset()); } @@ -505,6 +560,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RefPtr<RegisterID> profileHookRegister; if (generator.shouldEmitProfileHooks()) profileHookRegister = generator.newTemporary(); + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); RefPtr<RegisterID> thisRegister = generator.emitNode(m_args->m_listNode->m_expr); RefPtr<RegisterID> argsRegister; ArgumentListNode* args = m_args->m_listNode->m_next; @@ -518,7 +574,7 @@ RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, while ((args = args->m_next)) generator.emitNode(args->m_expr); - generator.emitCallVarargs(finalDestinationOrIgnored.get(), base.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset()); + generator.emitCallVarargs(finalDestinationOrIgnored.get(), realFunction.get(), thisRegister.get(), argsRegister.get(), generator.newTemporary(), profileHookRegister.get(), divot(), startOffset(), endOffset()); } generator.emitJump(end.get()); } @@ -548,24 +604,21 @@ static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* ds RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { + ResolveResult resolveResult = generator.resolve(m_ident); + + if (RegisterID* local = resolveResult.local()) { + if (resolveResult.isReadOnly()) { if (dst == generator.ignoredResult()) return 0; return generator.emitToJSNumber(generator.finalDestination(dst), local); } - if (dst == generator.ignoredResult()) return emitPreIncOrDec(generator, local, m_operator); return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); } - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - bool requiresDynamicChecks = false; - if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { - RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); + if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { + RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult); RegisterID* oldValue; if (dst == generator.ignoredResult()) { oldValue = 0; @@ -573,13 +626,13 @@ RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, Regis } else { oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); } - generator.emitPutScopedVar(depth, index, value.get(), globalObject); + generator.emitPutStaticVar(resolveResult, value.get()); return oldValue; } - + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RefPtr<RegisterID> value = generator.newTemporary(); - RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); + RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), resolveResult, m_ident); RegisterID* oldValue; if (dst == generator.ignoredResult()) { oldValue = 0; @@ -651,11 +704,12 @@ RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, Registe RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (generator.registerFor(m_ident)) + ResolveResult resolveResult = generator.resolve(m_ident); + if (resolveResult.isRegister()) return generator.emitLoad(generator.finalDestination(dst), false); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); + RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident); return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); } @@ -706,13 +760,14 @@ RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RegisterID* local = generator.registerFor(m_ident)) { + ResolveResult resolveResult = generator.resolve(m_ident); + if (RegisterID* local = resolveResult.local()) { if (dst == generator.ignoredResult()) return 0; return generator.emitTypeOf(generator.finalDestination(dst), local); } - RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); + RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident); generator.emitGetById(scratch.get(), scratch.get(), m_ident); if (dst == generator.ignoredResult()) return 0; @@ -735,32 +790,28 @@ RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, Register RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RegisterID* local = generator.registerFor(m_ident)) { + ResolveResult resolveResult = generator.resolve(m_ident); + if (RegisterID* local = resolveResult.local()) { if (generator.isLocalConstant(m_ident)) { if (dst == generator.ignoredResult()) return 0; RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); } - emitPreIncOrDec(generator, local, m_operator); return generator.moveToDestinationIfNeeded(dst, local); } - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - bool requiresDynamicChecks = false; - if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { - RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); + if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { + RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult); emitPreIncOrDec(generator, propDst.get(), m_operator); - generator.emitPutScopedVar(depth, index, propDst.get(), globalObject); + generator.emitPutStaticVar(resolveResult, propDst.get()); return generator.moveToDestinationIfNeeded(dst, propDst.get()); } generator.emitExpressionInfo(divot(), startOffset(), endOffset()); RefPtr<RegisterID> propDst = generator.tempDestination(dst); - RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); + RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), resolveResult, m_ident); emitPreIncOrDec(generator, propDst.get(), m_operator); generator.emitPutById(base.get(), m_ident, propDst.get()); return generator.moveToDestinationIfNeeded(dst, propDst.get()); @@ -1148,10 +1199,11 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { + ResolveResult resolveResult = generator.resolve(m_ident); + + if (RegisterID *local = resolveResult.local()) { + if (resolveResult.isReadOnly()) return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - } if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { RefPtr<RegisterID> result = generator.newTemporary(); @@ -1165,20 +1217,16 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re return generator.moveToDestinationIfNeeded(dst, result); } - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - bool requiresDynamicChecks = false; - if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { - RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); + if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { + RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult); RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - generator.emitPutScopedVar(depth, index, result, globalObject); + generator.emitPutStaticVar(resolveResult, result); return result; } RefPtr<RegisterID> src1 = generator.tempDestination(dst); generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0); - RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); + RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), resolveResult, m_ident); RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); return generator.emitPutById(base.get(), m_ident, result); } @@ -1187,27 +1235,24 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) { - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) + ResolveResult resolveResult = generator.resolve(m_ident); + + if (RegisterID *local = resolveResult.local()) { + if (resolveResult.isReadOnly()) return generator.emitNode(dst, m_right); - RegisterID* result = generator.emitNode(local, m_right); return generator.moveToDestinationIfNeeded(dst, result); } - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - bool requiresDynamicChecks = false; - if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) { + if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { if (dst == generator.ignoredResult()) dst = 0; RegisterID* value = generator.emitNode(dst, m_right); - generator.emitPutScopedVar(depth, index, value, globalObject); + generator.emitPutStaticVar(resolveResult, value); return value; } - RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident); + RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, m_ident); if (dst == generator.ignoredResult()) dst = 0; RegisterID* value = generator.emitNode(dst, m_right); @@ -1295,8 +1340,10 @@ RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) { + ResolveResult resolveResult = generator.resolveConstDecl(m_ident); + // FIXME: This code does not match the behavior of const in Firefox. - if (RegisterID* local = generator.constRegisterFor(m_ident)) { + if (RegisterID* local = resolveResult.local()) { if (!m_init) return local; @@ -1305,27 +1352,15 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); - ScopeChainIterator iter = generator.scopeChain()->begin(); - ScopeChainIterator end = generator.scopeChain()->end(); - size_t depth = 0; - for (; iter != end; ++iter, ++depth) { - JSObject* currentScope = iter->get(); - if (!currentScope->isVariableObject()) - continue; - JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope); - SymbolTableEntry entry = currentVariableObject->symbolTable().get(m_ident.impl()); - if (entry.isNull()) - continue; - - return generator.emitPutScopedVar(generator.scopeDepth() + depth, entry.getIndex(), value.get(), currentVariableObject->isGlobalObject() ? currentVariableObject : 0); - } - + if (resolveResult.isStatic()) + return generator.emitPutStaticVar(resolveResult, value.get()); + if (generator.codeType() != EvalCode) return value.get(); // FIXME: While this code should only be hit in an eval block, it will assign // to the wrong base if m_ident exists in an intervening with scope. - RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); + RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), resolveResult, m_ident); return generator.emitPutById(base.get(), m_ident, value.get()); } @@ -1596,11 +1631,12 @@ RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* ds bool optimizedForinAccess = false; if (m_lexpr->isResolveNode()) { const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); - propertyName = generator.registerFor(ident); + ResolveResult resolveResult = generator.resolve(ident); + propertyName = resolveResult.local(); if (!propertyName) { propertyName = generator.newTemporary(); RefPtr<RegisterID> protect = propertyName; - RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident); + RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, ident); generator.emitExpressionInfo(divot(), startOffset(), endOffset()); generator.emitPutById(base, ident, propertyName); @@ -1933,13 +1969,7 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) // Uncaught exception path: the catch block. RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); - if (m_catchHasEval) { - RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary()); - generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get()); - generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get()); - generator.emitPushScope(exceptionRegister.get()); - } else - generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); + generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); generator.emitNode(dst, m_catchBlock); generator.emitPopScope(); generator.emitLabel(catchEndLabel.get()); |