diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/JavaScriptCore/bytecompiler | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/JavaScriptCore/bytecompiler')
3 files changed, 108 insertions, 75 deletions
diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 4a6f4653e..a520a4c78 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * Copyright (C) 2012 Igalia, S.L. * @@ -200,10 +200,10 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe { int index = m_calleeRegisters.size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry); + SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); - if (!result.second) { - r0 = ®isterFor(result.first->second.getIndex()); + if (!result.isNewEntry) { + r0 = ®isterFor(result.iterator->second.getIndex()); return false; } @@ -215,9 +215,9 @@ int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant) { int index = symbolTable().size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry); - if (!result.second) - index = result.first->second.getIndex(); + SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); + if (!result.isNewEntry) + index = result.iterator->second.getIndex(); return index; } @@ -968,24 +968,24 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond unsigned BytecodeGenerator::addConstant(const Identifier& ident) { StringImpl* rep = ident.impl(); - pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers()); - if (result.second) // new entry + IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers()); + if (result.isNewEntry) m_codeBlock->addIdentifier(Identifier(m_globalData, rep)); - return result.first->second; + return result.iterator->second; } RegisterID* BytecodeGenerator::addConstantValue(JSValue v) { int index = m_nextConstantOffset; - pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset); - if (result.second) { + JSValueMap::AddResult result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset); + if (result.isNewEntry) { m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); ++m_nextConstantOffset; m_codeBlock->addConstant(JSValue(v)); } else - index = result.first->second; + index = result.iterator->second; return &m_constantPoolRegisters[index]; } @@ -1132,7 +1132,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) // work correctly with NaN as a key. if (isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) return emitLoad(dst, jsNumber(number)); - JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second; + JSValue& valueInMap = m_numberMap.add(number, JSValue()).iterator->second; if (!valueInMap) valueInMap = jsNumber(number); return emitLoad(dst, valueInMap); @@ -1140,7 +1140,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier) { - JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second; + JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).iterator->second; if (!stringInMap) stringInMap = jsOwnedString(globalData(), identifier.ustring()); return emitLoad(dst, JSValue(stringInMap)); @@ -1185,7 +1185,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property) flags |= ResolveResult::DynamicFlag; break; } - JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope); + JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope); SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl()); // Found the property @@ -1242,7 +1242,7 @@ ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property) JSObject* currentScope = iter->get(); if (!currentScope->isVariableObject()) continue; - JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope); + JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope); SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl()); if (entry.isNull()) continue; @@ -1648,7 +1648,7 @@ unsigned BytecodeGenerator::addConstantBuffer(unsigned length) JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier) { - JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second; + JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).iterator->second; if (!stringInMap) { stringInMap = jsString(globalData(), identifier.ustring()); addConstantValue(stringInMap); @@ -1718,10 +1718,10 @@ RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function) { - std::pair<FunctionOffsetMap::iterator, bool> ptr = m_functionOffsets.add(function, 0); - if (ptr.second) - ptr.first->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)); - return emitNewFunctionInternal(dst, ptr.first->second, true); + FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0); + if (ptr.isNewEntry) + ptr.iterator->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)); + return emitNewFunctionInternal(dst, ptr.iterator->second, true); } RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck) @@ -2004,11 +2004,19 @@ void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, in instructions().append(lastLine); } -void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst) +void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock) { ControlFlowContext scope; scope.isFinallyBlock = true; - FinallyContext context = { target, retAddrDst }; + FinallyContext context = { + finallyBlock, + m_scopeContextStack.size(), + m_switchContextStack.size(), + m_forInContextStack.size(), + m_labelScopes.size(), + m_finallyDepth, + m_dynamicScopeDepth + }; scope.finallyContext = context; m_scopeContextStack.append(scope); m_finallyDepth++; @@ -2134,9 +2142,63 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro instructions().append(nextInsn->bind(begin, instructions().size())); emitLabel(nextInsn.get()); } - + + Vector<ControlFlowContext> savedScopeContextStack; + Vector<SwitchInfo> savedSwitchContextStack; + Vector<ForInContext> savedForInContextStack; + SegmentedVector<LabelScope, 8> savedLabelScopes; while (topScope > bottomScope && topScope->isFinallyBlock) { - emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr); + // Save the current state of the world while instating the state of the world + // for the finally block. + FinallyContext finallyContext = topScope->finallyContext; + bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size(); + bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size(); + bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size(); + bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size(); + int topScopeIndex = -1; + int bottomScopeIndex = -1; + if (flipScopes) { + topScopeIndex = topScope - m_scopeContextStack.begin(); + bottomScopeIndex = bottomScope - m_scopeContextStack.begin(); + savedScopeContextStack = m_scopeContextStack; + m_scopeContextStack.shrink(finallyContext.scopeContextStackSize); + } + if (flipSwitches) { + savedSwitchContextStack = m_switchContextStack; + m_switchContextStack.shrink(finallyContext.switchContextStackSize); + } + if (flipForIns) { + savedForInContextStack = m_forInContextStack; + m_forInContextStack.shrink(finallyContext.forInContextStackSize); + } + if (flipLabelScopes) { + savedLabelScopes = m_labelScopes; + while (m_labelScopes.size() > finallyContext.labelScopesSize) + m_labelScopes.removeLast(); + } + int savedFinallyDepth = m_finallyDepth; + m_finallyDepth = finallyContext.finallyDepth; + int savedDynamicScopeDepth = m_dynamicScopeDepth; + m_dynamicScopeDepth = finallyContext.dynamicScopeDepth; + + // Emit the finally block. + emitNode(finallyContext.finallyBlock); + + // Restore the state of the world. + if (flipScopes) { + m_scopeContextStack = savedScopeContextStack; + topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds + bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1. + } + if (flipSwitches) + m_switchContextStack = savedSwitchContextStack; + if (flipForIns) + m_forInContextStack = savedForInContextStack; + if (flipLabelScopes) + m_labelScopes = savedLabelScopes; + m_finallyDepth = savedFinallyDepth; + m_dynamicScopeDepth = savedDynamicScopeDepth; + --topScope; } } @@ -2216,23 +2278,6 @@ void BytecodeGenerator::emitThrowReferenceError(const UString& message) instructions().append(addConstantValue(jsString(globalData(), message))->index()); } -PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally) -{ - size_t begin = instructions().size(); - - emitOpcode(op_jsr); - instructions().append(retAddrDst->index()); - instructions().append(finally->bind(begin, instructions().size())); - emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it. - return finally; -} - -void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc) -{ - emitOpcode(op_sret); - instructions().append(retAddrSrc->index()); -} - void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value) { ControlFlowContext context; diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index e7fe236e5..a71bbb785 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * Copyright (C) 2012 Igalia, S.L. * @@ -71,8 +71,13 @@ namespace JSC { }; struct FinallyContext { - Label* finallyAddr; - RegisterID* retAddrDst; + StatementNode* finallyBlock; + unsigned scopeContextStackSize; + unsigned switchContextStackSize; + unsigned forInContextStackSize; + unsigned labelScopesSize; + int finallyDepth; + int dynamicScopeDepth; }; struct ControlFlowContext { @@ -479,9 +484,6 @@ namespace JSC { PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target); PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth); - PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*); - void emitSubroutineReturn(RegisterID* retAddrSrc); - RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget); RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target); @@ -504,7 +506,7 @@ namespace JSC { int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } bool hasFinaliser() { return m_finallyDepth != 0; } - void pushFinallyContext(Label* target, RegisterID* returnAddrDst); + void pushFinallyContext(StatementNode* finallyBlock); void popFinallyContext(); void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister) diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index bb95cafb6..e23f1e4d6 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) -* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -256,9 +256,9 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe continue; GetterSetterPair pair(node, static_cast<PropertyNode*>(0)); - std::pair<GetterSetterMap::iterator, bool> result = map.add(node->name().impl(), pair); - if (!result.second) - result.first->second.second = node; + GetterSetterMap::AddResult result = map.add(node->name().impl(), pair); + if (!result.isNewEntry) + result.iterator->second.second = node; } // Iterate over the remaining properties in the list. @@ -1727,7 +1727,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RefPtr<RegisterID> returnRegister; if (generator.scopeDepth()) { RefPtr<Label> l0 = generator.newLabel(); - if (generator.hasFinaliser() && !r0->isTemporary()) { + if (generator.hasFinaliser()) { returnRegister = generator.emitMove(generator.newTemporary(), r0); r0 = returnRegister.get(); } @@ -1957,13 +1957,8 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); RefPtr<Label> tryStartLabel = generator.newLabel(); - RefPtr<Label> finallyStart; - RefPtr<RegisterID> finallyReturnAddr; - if (m_finallyBlock) { - finallyStart = generator.newLabel(); - finallyReturnAddr = generator.newTemporary(); - generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); - } + if (m_finallyBlock) + generator.pushFinallyContext(m_finallyBlock); generator.emitLabel(tryStartLabel.get()); generator.emitNode(dst, m_tryBlock); @@ -1985,27 +1980,18 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) if (m_finallyBlock) { generator.popFinallyContext(); - // there may be important registers live at the time we jump - // to a finally block (such as for a return or throw) so we - // ref the highest register ever used as a conservative - // approach to not clobbering anything important - RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); + RefPtr<Label> finallyEndLabel = generator.newLabel(); - // Normal path: invoke the finally block, then jump over it. - generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); + // Normal path: run the finally code, and jump to the end. + generator.emitNode(dst, m_finallyBlock); generator.emitJump(finallyEndLabel.get()); // Uncaught exception path: invoke the finally block, then re-throw the exception. RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); - generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); - generator.emitThrow(tempExceptionRegister.get()); - - // The finally block. - generator.emitLabel(finallyStart.get()); generator.emitNode(dst, m_finallyBlock); - generator.emitSubroutineReturn(finallyReturnAddr.get()); + generator.emitThrow(tempExceptionRegister.get()); generator.emitLabel(finallyEndLabel.get()); } |