source: webkit/trunk/JavaScriptCore/bytecode/CodeBlock.cpp@ 42989

Last change on this file since 42989 was 42989, checked in by [email protected], 16 years ago

JavaScriptCore:

2009-04-28 Geoffrey Garen <[email protected]>

Rubber stamped by Beth Dakin.


Removed scaffolding supporting dynamically converting between 32bit and
64bit value representations.

  • API/JSCallbackConstructor.cpp: (JSC::constructJSCallback):
  • API/JSCallbackFunction.cpp: (JSC::JSCallbackFunction::call):
  • API/JSCallbackObjectFunctions.h: (JSC::::construct): (JSC::::call):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::getConstant):
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitEqualityOp):
  • interpreter/CallFrame.cpp: (JSC::CallFrame::thisValue):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::callEval): (JSC::Interpreter::throwException): (JSC::Interpreter::createExceptionScope): (JSC::Interpreter::privateExecute): (JSC::Interpreter::retrieveArguments):
  • interpreter/Register.h: (JSC::Register::): (JSC::Register::Register): (JSC::Register::jsValue): (JSC::Register::marked): (JSC::Register::mark): (JSC::Register::i): (JSC::Register::activation): (JSC::Register::arguments): (JSC::Register::callFrame): (JSC::Register::codeBlock): (JSC::Register::function): (JSC::Register::propertyNameIterator): (JSC::Register::scopeChain): (JSC::Register::vPC):
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_op_call_NotJSFunction): (JSC::JITStubs::cti_op_load_varargs): (JSC::JITStubs::cti_op_call_eval):
  • jsc.cpp: (functionPrint): (functionDebug): (functionRun): (functionLoad):
  • runtime/ArgList.h: (JSC::ArgList::at):
  • runtime/Arguments.cpp: (JSC::Arguments::copyToRegisters): (JSC::Arguments::fillArgList): (JSC::Arguments::getOwnPropertySlot):
  • runtime/ArrayConstructor.cpp: (JSC::constructArrayWithSizeQuirk):
  • runtime/ArrayPrototype.cpp: (JSC::arrayProtoFuncJoin): (JSC::arrayProtoFuncConcat): (JSC::arrayProtoFuncPush): (JSC::arrayProtoFuncSlice): (JSC::arrayProtoFuncSort): (JSC::arrayProtoFuncSplice): (JSC::arrayProtoFuncUnShift): (JSC::arrayProtoFuncFilter): (JSC::arrayProtoFuncMap): (JSC::arrayProtoFuncEvery): (JSC::arrayProtoFuncForEach): (JSC::arrayProtoFuncSome): (JSC::arrayProtoFuncReduce): (JSC::arrayProtoFuncReduceRight): (JSC::arrayProtoFuncIndexOf): (JSC::arrayProtoFuncLastIndexOf):
  • runtime/BooleanConstructor.cpp: (JSC::constructBoolean): (JSC::callBooleanConstructor):
  • runtime/DateConstructor.cpp: (JSC::constructDate): (JSC::dateParse): (JSC::dateUTC):
  • runtime/DatePrototype.cpp: (JSC::formatLocaleDate): (JSC::fillStructuresUsingTimeArgs): (JSC::fillStructuresUsingDateArgs): (JSC::dateProtoFuncSetTime): (JSC::dateProtoFuncSetYear):
  • runtime/ErrorConstructor.cpp: (JSC::constructError):
  • runtime/FunctionConstructor.cpp: (JSC::constructFunction):
  • runtime/FunctionPrototype.cpp: (JSC::functionProtoFuncApply): (JSC::functionProtoFuncCall):
  • runtime/JSArray.cpp: (JSC::JSArray::JSArray): (JSC::constructArray):
  • runtime/JSArray.h:
  • runtime/JSGlobalObjectFunctions.cpp: (JSC::encode): (JSC::decode): (JSC::globalFuncEval): (JSC::globalFuncParseInt): (JSC::globalFuncParseFloat): (JSC::globalFuncIsNaN): (JSC::globalFuncIsFinite): (JSC::globalFuncEscape): (JSC::globalFuncUnescape): (JSC::globalFuncJSCPrint):
  • runtime/MathObject.cpp: (JSC::mathProtoFuncAbs): (JSC::mathProtoFuncACos): (JSC::mathProtoFuncASin): (JSC::mathProtoFuncATan): (JSC::mathProtoFuncATan2): (JSC::mathProtoFuncCeil): (JSC::mathProtoFuncCos): (JSC::mathProtoFuncExp): (JSC::mathProtoFuncFloor): (JSC::mathProtoFuncLog): (JSC::mathProtoFuncMax): (JSC::mathProtoFuncMin): (JSC::mathProtoFuncPow): (JSC::mathProtoFuncRound): (JSC::mathProtoFuncSin): (JSC::mathProtoFuncSqrt): (JSC::mathProtoFuncTan):
  • runtime/NativeErrorConstructor.cpp: (JSC::NativeErrorConstructor::construct):
  • runtime/NumberConstructor.cpp: (JSC::constructWithNumberConstructor): (JSC::callNumberConstructor):
  • runtime/NumberPrototype.cpp: (JSC::numberProtoFuncToString): (JSC::numberProtoFuncToFixed): (JSC::numberProtoFuncToExponential): (JSC::numberProtoFuncToPrecision):
  • runtime/ObjectConstructor.cpp: (JSC::constructObject):
  • runtime/ObjectPrototype.cpp: (JSC::objectProtoFuncHasOwnProperty): (JSC::objectProtoFuncIsPrototypeOf): (JSC::objectProtoFuncDefineGetter): (JSC::objectProtoFuncDefineSetter): (JSC::objectProtoFuncLookupGetter): (JSC::objectProtoFuncLookupSetter): (JSC::objectProtoFuncPropertyIsEnumerable):
  • runtime/PropertySlot.h: (JSC::PropertySlot::getValue):
  • runtime/RegExpConstructor.cpp: (JSC::constructRegExp):
  • runtime/RegExpObject.cpp: (JSC::RegExpObject::match):
  • runtime/RegExpPrototype.cpp: (JSC::regExpProtoFuncCompile):
  • runtime/StringConstructor.cpp: (JSC::stringFromCharCodeSlowCase): (JSC::stringFromCharCode): (JSC::constructWithStringConstructor): (JSC::callStringConstructor):
  • runtime/StringPrototype.cpp: (JSC::stringProtoFuncReplace): (JSC::stringProtoFuncCharAt): (JSC::stringProtoFuncCharCodeAt): (JSC::stringProtoFuncConcat): (JSC::stringProtoFuncIndexOf): (JSC::stringProtoFuncLastIndexOf): (JSC::stringProtoFuncMatch): (JSC::stringProtoFuncSearch): (JSC::stringProtoFuncSlice): (JSC::stringProtoFuncSplit): (JSC::stringProtoFuncSubstr): (JSC::stringProtoFuncSubstring): (JSC::stringProtoFuncLocaleCompare): (JSC::stringProtoFuncFontcolor): (JSC::stringProtoFuncFontsize): (JSC::stringProtoFuncAnchor): (JSC::stringProtoFuncLink):

WebCore:

2009-04-28 Geoffrey Garen <[email protected]>

Rubber stamped by Beth Dakin.


Removed scaffolding supporting dynamically converting between 32bit and
64bit value representations.

  • bindings/js/JSAudioConstructor.cpp: (WebCore::constructAudio):
  • bindings/js/JSCanvasRenderingContext2DCustom.cpp: (WebCore::JSCanvasRenderingContext2D::setFillColor): (WebCore::JSCanvasRenderingContext2D::setStrokeColor): (WebCore::JSCanvasRenderingContext2D::strokeRect): (WebCore::JSCanvasRenderingContext2D::drawImage): (WebCore::JSCanvasRenderingContext2D::drawImageFromRect): (WebCore::JSCanvasRenderingContext2D::setShadow): (WebCore::JSCanvasRenderingContext2D::createPattern): (WebCore::JSCanvasRenderingContext2D::putImageData): (WebCore::JSCanvasRenderingContext2D::fillText): (WebCore::JSCanvasRenderingContext2D::strokeText):
  • bindings/js/JSClipboardCustom.cpp: (WebCore::JSClipboard::clearData): (WebCore::JSClipboard::getData): (WebCore::JSClipboard::setData): (WebCore::JSClipboard::setDragImage):
  • bindings/js/JSDOMApplicationCacheCustom.cpp: (WebCore::JSDOMApplicationCache::hasItem): (WebCore::JSDOMApplicationCache::add): (WebCore::JSDOMApplicationCache::remove): (WebCore::JSDOMApplicationCache::addEventListener): (WebCore::JSDOMApplicationCache::removeEventListener):
  • bindings/js/JSDOMStringListCustom.cpp: (WebCore::JSDOMStringList::item):
  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::JSDOMWindow::open): (WebCore::JSDOMWindow::showModalDialog): (WebCore::JSDOMWindow::postMessage): (WebCore::JSDOMWindow::setTimeout): (WebCore::JSDOMWindow::setInterval): (WebCore::JSDOMWindow::atob): (WebCore::JSDOMWindow::btoa): (WebCore::JSDOMWindow::addEventListener): (WebCore::JSDOMWindow::removeEventListener):
  • bindings/js/JSDatabaseCustom.cpp: (WebCore::JSDatabase::changeVersion): (WebCore::JSDatabase::transaction):
  • bindings/js/JSElementCustom.cpp: (WebCore::JSElement::setAttribute): (WebCore::JSElement::setAttributeNode): (WebCore::JSElement::setAttributeNS): (WebCore::JSElement::setAttributeNodeNS):
  • bindings/js/JSGeolocationCustom.cpp: (WebCore::JSGeolocation::getCurrentPosition): (WebCore::JSGeolocation::watchPosition):
  • bindings/js/JSHTMLCollectionCustom.cpp: (WebCore::callHTMLCollection): (WebCore::JSHTMLCollection::item): (WebCore::JSHTMLCollection::namedItem):
  • bindings/js/JSHTMLDocumentCustom.cpp: (WebCore::documentWrite):
  • bindings/js/JSHTMLInputElementCustom.cpp: (WebCore::JSHTMLInputElement::setSelectionRange):
  • bindings/js/JSHTMLOptionsCollectionCustom.cpp: (WebCore::JSHTMLOptionsCollection::add):
  • bindings/js/JSHTMLSelectElementCustom.cpp: (WebCore::JSHTMLSelectElement::remove):
  • bindings/js/JSImageConstructor.cpp: (WebCore::constructImage):
  • bindings/js/JSInspectorControllerCustom.cpp: (WebCore::JSInspectorController::highlightDOMNode): (WebCore::JSInspectorController::addResourceSourceToFrame): (WebCore::JSInspectorController::addSourceToFrame): (WebCore::JSInspectorController::getResourceDocumentNode): (WebCore::JSInspectorController::search): (WebCore::JSInspectorController::databaseTableNames): (WebCore::JSInspectorController::setting): (WebCore::JSInspectorController::setSetting): (WebCore::JSInspectorController::wrapCallback):
  • bindings/js/JSJavaScriptCallFrameCustom.cpp: (WebCore::JSJavaScriptCallFrame::evaluate):
  • bindings/js/JSLocationCustom.cpp: (WebCore::JSLocation::replace): (WebCore::JSLocation::assign):
  • bindings/js/JSMessagePortCustom.cpp: (WebCore::JSMessagePort::startConversation): (WebCore::JSMessagePort::addEventListener): (WebCore::JSMessagePort::removeEventListener):
  • bindings/js/JSNodeCustom.cpp: (WebCore::JSNode::insertBefore): (WebCore::JSNode::replaceChild): (WebCore::JSNode::removeChild): (WebCore::JSNode::appendChild): (WebCore::JSNode::addEventListener): (WebCore::JSNode::removeEventListener):
  • bindings/js/JSNodeFilterCustom.cpp: (WebCore::JSNodeFilter::acceptNode):
  • bindings/js/JSNodeListCustom.cpp: (WebCore::callNodeList):
  • bindings/js/JSOptionConstructor.cpp: (WebCore::constructHTMLOptionElement):
  • bindings/js/JSQuarantinedObjectWrapper.cpp: (WebCore::JSQuarantinedObjectWrapper::construct): (WebCore::JSQuarantinedObjectWrapper::call):
  • bindings/js/JSSQLResultSetRowListCustom.cpp: (WebCore::JSSQLResultSetRowList::item):
  • bindings/js/JSSQLTransactionCustom.cpp: (WebCore::JSSQLTransaction::executeSql):
  • bindings/js/JSSVGElementInstanceCustom.cpp: (WebCore::JSSVGElementInstance::addEventListener): (WebCore::JSSVGElementInstance::removeEventListener):
  • bindings/js/JSSVGLengthCustom.cpp: (WebCore::JSSVGLength::convertToSpecifiedUnits):
  • bindings/js/JSSVGMatrixCustom.cpp: (WebCore::JSSVGMatrix::rotateFromVector):
  • bindings/js/JSSVGPathSegListCustom.cpp: (WebCore::JSSVGPathSegList::initialize): (WebCore::JSSVGPathSegList::getItem): (WebCore::JSSVGPathSegList::insertItemBefore): (WebCore::JSSVGPathSegList::replaceItem): (WebCore::JSSVGPathSegList::removeItem): (WebCore::JSSVGPathSegList::appendItem):
  • bindings/js/JSSVGPointListCustom.cpp: (WebCore::JSSVGPointList::initialize): (WebCore::JSSVGPointList::getItem): (WebCore::JSSVGPointList::insertItemBefore): (WebCore::JSSVGPointList::replaceItem): (WebCore::JSSVGPointList::removeItem): (WebCore::JSSVGPointList::appendItem):
  • bindings/js/JSSVGTransformListCustom.cpp: (WebCore::JSSVGTransformList::initialize): (WebCore::JSSVGTransformList::getItem): (WebCore::JSSVGTransformList::insertItemBefore): (WebCore::JSSVGTransformList::replaceItem): (WebCore::JSSVGTransformList::removeItem): (WebCore::JSSVGTransformList::appendItem):
  • bindings/js/JSWebKitCSSMatrixConstructor.cpp: (WebCore::constructWebKitCSSMatrix):
  • bindings/js/JSWebKitPointConstructor.cpp: (WebCore::constructWebKitPoint):
  • bindings/js/JSWorkerConstructor.cpp: (WebCore::constructWorker):
  • bindings/js/JSWorkerContextCustom.cpp: (WebCore::JSWorkerContext::importScripts): (WebCore::JSWorkerContext::addEventListener): (WebCore::JSWorkerContext::removeEventListener): (WebCore::JSWorkerContext::setTimeout): (WebCore::JSWorkerContext::setInterval):
  • bindings/js/JSWorkerCustom.cpp: (WebCore::JSWorker::addEventListener): (WebCore::JSWorker::removeEventListener):
  • bindings/js/JSXMLHttpRequestCustom.cpp: (WebCore::JSXMLHttpRequest::open): (WebCore::JSXMLHttpRequest::setRequestHeader): (WebCore::JSXMLHttpRequest::send): (WebCore::JSXMLHttpRequest::getResponseHeader): (WebCore::JSXMLHttpRequest::overrideMimeType): (WebCore::JSXMLHttpRequest::addEventListener): (WebCore::JSXMLHttpRequest::removeEventListener):
  • bindings/js/JSXMLHttpRequestUploadCustom.cpp: (WebCore::JSXMLHttpRequestUpload::addEventListener): (WebCore::JSXMLHttpRequestUpload::removeEventListener):
  • bindings/js/JSXSLTProcessorCustom.cpp: (WebCore::JSXSLTProcessor::importStylesheet): (WebCore::JSXSLTProcessor::transformToFragment): (WebCore::JSXSLTProcessor::transformToDocument): (WebCore::JSXSLTProcessor::setParameter): (WebCore::JSXSLTProcessor::getParameter): (WebCore::JSXSLTProcessor::removeParameter):
  • bindings/js/ScheduledAction.cpp: (WebCore::ScheduledAction::create): (WebCore::ScheduledAction::ScheduledAction):
  • bindings/js/ScheduledAction.h:
  • bindings/js/ScriptCallFrame.cpp: (WebCore::ScriptCallFrame::ScriptCallFrame):
  • bindings/js/ScriptCallFrame.h:
  • bindings/js/ScriptCallStack.cpp: (WebCore::ScriptCallStack::ScriptCallStack): (WebCore::ScriptCallStack::initialize):
  • bridge/c/c_instance.cpp: (JSC::Bindings::CInstance::invokeMethod): (JSC::Bindings::CInstance::invokeDefaultMethod): (JSC::Bindings::CInstance::invokeConstruct):
  • bridge/jni/jni_instance.cpp: (JavaInstance::invokeMethod):
  • bridge/objc/objc_instance.mm: (ObjcInstance::invokeMethod): (ObjcInstance::invokeDefaultMethod):

WebKit/mac:

2009-04-28 Geoffrey Garen <[email protected]>

Rubber stamped by Beth Dakin.


Removed scaffolding supporting dynamically converting between 32bit and
64bit value representations.

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm: (WebKit::NetscapePluginInstanceProxy::marshalValues):
File size: 63.3 KB
Line 
1/*
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <[email protected]>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "config.h"
31#include "CodeBlock.h"
32
33#include "JIT.h"
34#include "JSValue.h"
35#include "Interpreter.h"
36#include "Debugger.h"
37#include "BytecodeGenerator.h"
38#include <stdio.h>
39#include <wtf/StringExtras.h>
40
41#define DUMP_CODE_BLOCK_STATISTICS 0
42
43namespace JSC {
44
45#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
46
47static UString escapeQuotes(const UString& str)
48{
49 UString result = str;
50 int pos = 0;
51 while ((pos = result.find('\"', pos)) >= 0) {
52 result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1);
53 pos += 4;
54 }
55 return result;
56}
57
58static UString valueToSourceString(ExecState* exec, JSValuePtr val)
59{
60 if (val.isString()) {
61 UString result("\"");
62 result += escapeQuotes(val.toString(exec)) + "\"";
63 return result;
64 }
65
66 return val.toString(exec);
67}
68
69static CString registerName(int r)
70{
71 if (r == missingThisObjectMarker())
72 return "<null>";
73
74 return (UString("r") + UString::from(r)).UTF8String();
75}
76
77static CString constantName(ExecState* exec, int k, JSValuePtr value)
78{
79 return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String();
80}
81
82static CString idName(int id0, const Identifier& ident)
83{
84 return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String();
85}
86
87static UString regexpToSourceString(RegExp* regExp)
88{
89 UString pattern = UString("/") + regExp->pattern() + "/";
90 if (regExp->global())
91 pattern += "g";
92 if (regExp->ignoreCase())
93 pattern += "i";
94 if (regExp->multiline())
95 pattern += "m";
96
97 return pattern;
98}
99
100static CString regexpName(int re, RegExp* regexp)
101{
102 return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String();
103}
104
105static UString pointerToSourceString(void* p)
106{
107 char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
108 snprintf(buffer, sizeof(buffer), "%p", p);
109 return buffer;
110}
111
112NEVER_INLINE static const char* debugHookName(int debugHookID)
113{
114 switch (static_cast<DebugHookID>(debugHookID)) {
115 case DidEnterCallFrame:
116 return "didEnterCallFrame";
117 case WillLeaveCallFrame:
118 return "willLeaveCallFrame";
119 case WillExecuteStatement:
120 return "willExecuteStatement";
121 case WillExecuteProgram:
122 return "willExecuteProgram";
123 case DidExecuteProgram:
124 return "didExecuteProgram";
125 case DidReachBreakpoint:
126 return "didReachBreakpoint";
127 }
128
129 ASSERT_NOT_REACHED();
130 return "";
131}
132
133static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset)
134{
135 return it - begin + offset;
136}
137
138static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
139{
140 int r0 = (++it)->u.operand;
141 int r1 = (++it)->u.operand;
142
143 printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str());
144}
145
146static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op)
147{
148 int r0 = (++it)->u.operand;
149 int r1 = (++it)->u.operand;
150 int r2 = (++it)->u.operand;
151 printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
152}
153
154static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op)
155{
156 int r0 = (++it)->u.operand;
157 int offset = (++it)->u.operand;
158 printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset));
159}
160
161static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
162{
163 int r0 = (++it)->u.operand;
164 int r1 = (++it)->u.operand;
165 int id0 = (++it)->u.operand;
166 printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
167 it += 4;
168}
169
170static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op)
171{
172 int r0 = (++it)->u.operand;
173 int id0 = (++it)->u.operand;
174 int r1 = (++it)->u.operand;
175 printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
176 it += 4;
177}
178
179#if ENABLE(JIT)
180static bool isGlobalResolve(OpcodeID opcodeID)
181{
182 return opcodeID == op_resolve_global;
183}
184
185static bool isPropertyAccess(OpcodeID opcodeID)
186{
187 switch (opcodeID) {
188 case op_get_by_id_self:
189 case op_get_by_id_proto:
190 case op_get_by_id_chain:
191 case op_get_by_id_self_list:
192 case op_get_by_id_proto_list:
193 case op_put_by_id_transition:
194 case op_put_by_id_replace:
195 case op_get_by_id:
196 case op_put_by_id:
197 case op_get_by_id_generic:
198 case op_put_by_id_generic:
199 case op_get_array_length:
200 case op_get_string_length:
201 return true;
202 default:
203 return false;
204 }
205}
206
207static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
208{
209 size_t i = 0;
210 while (i < instructions.size()) {
211 OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode);
212 if (predicate(currentOpcode)) {
213 if (!--nth)
214 return i;
215 }
216 i += opcodeLengths[currentOpcode];
217 }
218
219 ASSERT_NOT_REACHED();
220 return 0;
221}
222
223static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
224{
225 printf(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().c_str());
226}
227
228static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
229{
230 switch (stubInfo.opcodeID) {
231 case op_get_by_id_self:
232 printf(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str());
233 return;
234 case op_get_by_id_proto:
235 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str());
236 return;
237 case op_get_by_id_chain:
238 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str());
239 return;
240 case op_get_by_id_self_list:
241 printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize);
242 return;
243 case op_get_by_id_proto_list:
244 printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize);
245 return;
246 case op_put_by_id_transition:
247 printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str());
248 return;
249 case op_put_by_id_replace:
250 printf(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str());
251 return;
252 case op_get_by_id:
253 printf(" [%4d] %s\n", instructionOffset, "get_by_id");
254 return;
255 case op_put_by_id:
256 printf(" [%4d] %s\n", instructionOffset, "put_by_id");
257 return;
258 case op_get_by_id_generic:
259 printf(" [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
260 return;
261 case op_put_by_id_generic:
262 printf(" [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
263 return;
264 case op_get_array_length:
265 printf(" [%4d] %s\n", instructionOffset, "op_get_array_length");
266 return;
267 case op_get_string_length:
268 printf(" [%4d] %s\n", instructionOffset, "op_get_string_length");
269 return;
270 default:
271 ASSERT_NOT_REACHED();
272 }
273}
274#endif
275
276void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
277{
278 unsigned instructionOffset = vPC - m_instructions.begin();
279 printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str());
280}
281
282void CodeBlock::printStructures(const Instruction* vPC) const
283{
284 Interpreter* interpreter = m_globalData->interpreter;
285 unsigned instructionOffset = vPC - m_instructions.begin();
286
287 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id)) {
288 printStructure("get_by_id", vPC, 4);
289 return;
290 }
291 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
292 printStructure("get_by_id_self", vPC, 4);
293 return;
294 }
295 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
296 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str());
297 return;
298 }
299 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
300 printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());
301 return;
302 }
303 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
304 printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str());
305 return;
306 }
307 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) {
308 printStructure("put_by_id", vPC, 4);
309 return;
310 }
311 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
312 printStructure("put_by_id_replace", vPC, 4);
313 return;
314 }
315 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
316 printStructure("resolve_global", vPC, 4);
317 return;
318 }
319
320 // These m_instructions doesn't ref Structures.
321 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct));
322}
323
324void CodeBlock::dump(ExecState* exec) const
325{
326 if (m_instructions.isEmpty()) {
327 printf("No instructions available.\n");
328 return;
329 }
330
331 size_t instructionCount = 0;
332
333 for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
334 ++instructionCount;
335
336 printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
337 static_cast<unsigned long>(instructionCount),
338 static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
339 this, m_numParameters, m_numCalleeRegisters);
340
341 Vector<Instruction>::const_iterator begin = m_instructions.begin();
342 Vector<Instruction>::const_iterator end = m_instructions.end();
343 for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
344 dump(exec, begin, it);
345
346 if (!m_identifiers.isEmpty()) {
347 printf("\nIdentifiers:\n");
348 size_t i = 0;
349 do {
350 printf(" id%u = %s\n", static_cast<unsigned>(i), m_identifiers[i].ascii());
351 ++i;
352 } while (i != m_identifiers.size());
353 }
354
355 if (!m_constantRegisters.isEmpty()) {
356 printf("\nConstants:\n");
357 unsigned registerIndex = m_numVars;
358 size_t i = 0;
359 do {
360 printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii());
361 ++i;
362 ++registerIndex;
363 } while (i < m_constantRegisters.size());
364 }
365
366 if (m_rareData && !m_rareData->m_unexpectedConstants.isEmpty()) {
367 printf("\nUnexpected Constants:\n");
368 size_t i = 0;
369 do {
370 printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_rareData->m_unexpectedConstants[i]).ascii());
371 ++i;
372 } while (i < m_rareData->m_unexpectedConstants.size());
373 }
374
375 if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
376 printf("\nm_regexps:\n");
377 size_t i = 0;
378 do {
379 printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());
380 ++i;
381 } while (i < m_rareData->m_regexps.size());
382 }
383
384#if ENABLE(JIT)
385 if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
386 printf("\nStructures:\n");
387
388 if (!m_globalResolveInfos.isEmpty()) {
389 size_t i = 0;
390 do {
391 printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
392 ++i;
393 } while (i < m_globalResolveInfos.size());
394 }
395 if (!m_structureStubInfos.isEmpty()) {
396 size_t i = 0;
397 do {
398 printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
399 ++i;
400 } while (i < m_structureStubInfos.size());
401 }
402#else
403 if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
404 printf("\nStructures:\n");
405
406 if (!m_globalResolveInstructions.isEmpty()) {
407 size_t i = 0;
408 do {
409 printStructures(&m_instructions[m_globalResolveInstructions[i]]);
410 ++i;
411 } while (i < m_globalResolveInstructions.size());
412 }
413 if (!m_propertyAccessInstructions.isEmpty()) {
414 size_t i = 0;
415 do {
416 printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
417 ++i;
418 } while (i < m_propertyAccessInstructions.size());
419 }
420#endif
421
422 if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
423 printf("\nException Handlers:\n");
424 unsigned i = 0;
425 do {
426 printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] }\n", i + 1, m_rareData->m_exceptionHandlers[i].start, m_rareData->m_exceptionHandlers[i].end, m_rareData->m_exceptionHandlers[i].target);
427 ++i;
428 } while (i < m_rareData->m_exceptionHandlers.size());
429 }
430
431 if (m_rareData && !m_rareData->m_immediateSwitchJumpTables.isEmpty()) {
432 printf("Immediate Switch Jump Tables:\n");
433 unsigned i = 0;
434 do {
435 printf(" %1d = {\n", i);
436 int entry = 0;
437 Vector<int32_t>::const_iterator end = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.end();
438 for (Vector<int32_t>::const_iterator iter = m_rareData->m_immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
439 if (!*iter)
440 continue;
441 printf("\t\t%4d => %04d\n", entry + m_rareData->m_immediateSwitchJumpTables[i].min, *iter);
442 }
443 printf(" }\n");
444 ++i;
445 } while (i < m_rareData->m_immediateSwitchJumpTables.size());
446 }
447
448 if (m_rareData && !m_rareData->m_characterSwitchJumpTables.isEmpty()) {
449 printf("\nCharacter Switch Jump Tables:\n");
450 unsigned i = 0;
451 do {
452 printf(" %1d = {\n", i);
453 int entry = 0;
454 Vector<int32_t>::const_iterator end = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.end();
455 for (Vector<int32_t>::const_iterator iter = m_rareData->m_characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
456 if (!*iter)
457 continue;
458 ASSERT(!((i + m_rareData->m_characterSwitchJumpTables[i].min) & ~0xFFFF));
459 UChar ch = static_cast<UChar>(entry + m_rareData->m_characterSwitchJumpTables[i].min);
460 printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
461 }
462 printf(" }\n");
463 ++i;
464 } while (i < m_rareData->m_characterSwitchJumpTables.size());
465 }
466
467 if (m_rareData && !m_rareData->m_stringSwitchJumpTables.isEmpty()) {
468 printf("\nString Switch Jump Tables:\n");
469 unsigned i = 0;
470 do {
471 printf(" %1d = {\n", i);
472 StringJumpTable::StringOffsetTable::const_iterator end = m_rareData->m_stringSwitchJumpTables[i].offsetTable.end();
473 for (StringJumpTable::StringOffsetTable::const_iterator iter = m_rareData->m_stringSwitchJumpTables[i].offsetTable.begin(); iter != end; ++iter)
474 printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second.branchOffset);
475 printf(" }\n");
476 ++i;
477 } while (i < m_rareData->m_stringSwitchJumpTables.size());
478 }
479
480 printf("\n");
481}
482
483void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
484{
485 int location = it - begin;
486 switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
487 case op_enter: {
488 printf("[%4d] enter\n", location);
489 break;
490 }
491 case op_enter_with_activation: {
492 int r0 = (++it)->u.operand;
493 printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str());
494 break;
495 }
496 case op_create_arguments: {
497 printf("[%4d] create_arguments\n", location);
498 break;
499 }
500 case op_convert_this: {
501 int r0 = (++it)->u.operand;
502 printf("[%4d] convert_this %s\n", location, registerName(r0).c_str());
503 break;
504 }
505 case op_unexpected_load: {
506 int r0 = (++it)->u.operand;
507 int k0 = (++it)->u.operand;
508 printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstant(k0)).c_str());
509 break;
510 }
511 case op_new_object: {
512 int r0 = (++it)->u.operand;
513 printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str());
514 break;
515 }
516 case op_new_array: {
517 int dst = (++it)->u.operand;
518 int argv = (++it)->u.operand;
519 int argc = (++it)->u.operand;
520 printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc);
521 break;
522 }
523 case op_new_regexp: {
524 int r0 = (++it)->u.operand;
525 int re0 = (++it)->u.operand;
526 printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str());
527 break;
528 }
529 case op_mov: {
530 int r0 = (++it)->u.operand;
531 int r1 = (++it)->u.operand;
532 printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
533 break;
534 }
535 case op_not: {
536 printUnaryOp(location, it, "not");
537 break;
538 }
539 case op_eq: {
540 printBinaryOp(location, it, "eq");
541 break;
542 }
543 case op_eq_null: {
544 printUnaryOp(location, it, "eq_null");
545 break;
546 }
547 case op_neq: {
548 printBinaryOp(location, it, "neq");
549 break;
550 }
551 case op_neq_null: {
552 printUnaryOp(location, it, "neq_null");
553 break;
554 }
555 case op_stricteq: {
556 printBinaryOp(location, it, "stricteq");
557 break;
558 }
559 case op_nstricteq: {
560 printBinaryOp(location, it, "nstricteq");
561 break;
562 }
563 case op_less: {
564 printBinaryOp(location, it, "less");
565 break;
566 }
567 case op_lesseq: {
568 printBinaryOp(location, it, "lesseq");
569 break;
570 }
571 case op_pre_inc: {
572 int r0 = (++it)->u.operand;
573 printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str());
574 break;
575 }
576 case op_pre_dec: {
577 int r0 = (++it)->u.operand;
578 printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str());
579 break;
580 }
581 case op_post_inc: {
582 printUnaryOp(location, it, "post_inc");
583 break;
584 }
585 case op_post_dec: {
586 printUnaryOp(location, it, "post_dec");
587 break;
588 }
589 case op_to_jsnumber: {
590 printUnaryOp(location, it, "to_jsnumber");
591 break;
592 }
593 case op_negate: {
594 printUnaryOp(location, it, "negate");
595 break;
596 }
597 case op_add: {
598 printBinaryOp(location, it, "add");
599 ++it;
600 break;
601 }
602 case op_mul: {
603 printBinaryOp(location, it, "mul");
604 ++it;
605 break;
606 }
607 case op_div: {
608 printBinaryOp(location, it, "div");
609 break;
610 }
611 case op_mod: {
612 printBinaryOp(location, it, "mod");
613 break;
614 }
615 case op_sub: {
616 printBinaryOp(location, it, "sub");
617 ++it;
618 break;
619 }
620 case op_lshift: {
621 printBinaryOp(location, it, "lshift");
622 break;
623 }
624 case op_rshift: {
625 printBinaryOp(location, it, "rshift");
626 break;
627 }
628 case op_urshift: {
629 printBinaryOp(location, it, "urshift");
630 break;
631 }
632 case op_bitand: {
633 printBinaryOp(location, it, "bitand");
634 ++it;
635 break;
636 }
637 case op_bitxor: {
638 printBinaryOp(location, it, "bitxor");
639 ++it;
640 break;
641 }
642 case op_bitor: {
643 printBinaryOp(location, it, "bitor");
644 ++it;
645 break;
646 }
647 case op_bitnot: {
648 printUnaryOp(location, it, "bitnot");
649 break;
650 }
651 case op_instanceof: {
652 int r0 = (++it)->u.operand;
653 int r1 = (++it)->u.operand;
654 int r2 = (++it)->u.operand;
655 int r3 = (++it)->u.operand;
656 printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str());
657 break;
658 }
659 case op_typeof: {
660 printUnaryOp(location, it, "typeof");
661 break;
662 }
663 case op_is_undefined: {
664 printUnaryOp(location, it, "is_undefined");
665 break;
666 }
667 case op_is_boolean: {
668 printUnaryOp(location, it, "is_boolean");
669 break;
670 }
671 case op_is_number: {
672 printUnaryOp(location, it, "is_number");
673 break;
674 }
675 case op_is_string: {
676 printUnaryOp(location, it, "is_string");
677 break;
678 }
679 case op_is_object: {
680 printUnaryOp(location, it, "is_object");
681 break;
682 }
683 case op_is_function: {
684 printUnaryOp(location, it, "is_function");
685 break;
686 }
687 case op_in: {
688 printBinaryOp(location, it, "in");
689 break;
690 }
691 case op_resolve: {
692 int r0 = (++it)->u.operand;
693 int id0 = (++it)->u.operand;
694 printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
695 break;
696 }
697 case op_resolve_skip: {
698 int r0 = (++it)->u.operand;
699 int id0 = (++it)->u.operand;
700 int skipLevels = (++it)->u.operand;
701 printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels);
702 break;
703 }
704 case op_resolve_global: {
705 int r0 = (++it)->u.operand;
706 JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
707 int id0 = (++it)->u.operand;
708 printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str());
709 it += 2;
710 break;
711 }
712 case op_get_scoped_var: {
713 int r0 = (++it)->u.operand;
714 int index = (++it)->u.operand;
715 int skipLevels = (++it)->u.operand;
716 printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels);
717 break;
718 }
719 case op_put_scoped_var: {
720 int index = (++it)->u.operand;
721 int skipLevels = (++it)->u.operand;
722 int r0 = (++it)->u.operand;
723 printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str());
724 break;
725 }
726 case op_get_global_var: {
727 int r0 = (++it)->u.operand;
728 JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
729 int index = (++it)->u.operand;
730 printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index);
731 break;
732 }
733 case op_put_global_var: {
734 JSValuePtr scope = JSValuePtr((++it)->u.jsCell);
735 int index = (++it)->u.operand;
736 int r0 = (++it)->u.operand;
737 printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str());
738 break;
739 }
740 case op_resolve_base: {
741 int r0 = (++it)->u.operand;
742 int id0 = (++it)->u.operand;
743 printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str());
744 break;
745 }
746 case op_resolve_with_base: {
747 int r0 = (++it)->u.operand;
748 int r1 = (++it)->u.operand;
749 int id0 = (++it)->u.operand;
750 printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
751 break;
752 }
753 case op_resolve_func: {
754 int r0 = (++it)->u.operand;
755 int r1 = (++it)->u.operand;
756 int id0 = (++it)->u.operand;
757 printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
758 break;
759 }
760 case op_get_by_id: {
761 printGetByIdOp(location, it, m_identifiers, "get_by_id");
762 break;
763 }
764 case op_get_by_id_self: {
765 printGetByIdOp(location, it, m_identifiers, "get_by_id_self");
766 break;
767 }
768 case op_get_by_id_self_list: {
769 printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list");
770 break;
771 }
772 case op_get_by_id_proto: {
773 printGetByIdOp(location, it, m_identifiers, "get_by_id_proto");
774 break;
775 }
776 case op_get_by_id_proto_list: {
777 printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list");
778 break;
779 }
780 case op_get_by_id_chain: {
781 printGetByIdOp(location, it, m_identifiers, "get_by_id_chain");
782 break;
783 }
784 case op_get_by_id_generic: {
785 printGetByIdOp(location, it, m_identifiers, "get_by_id_generic");
786 break;
787 }
788 case op_get_array_length: {
789 printGetByIdOp(location, it, m_identifiers, "get_array_length");
790 break;
791 }
792 case op_get_string_length: {
793 printGetByIdOp(location, it, m_identifiers, "get_string_length");
794 break;
795 }
796 case op_put_by_id: {
797 printPutByIdOp(location, it, m_identifiers, "put_by_id");
798 break;
799 }
800 case op_put_by_id_replace: {
801 printPutByIdOp(location, it, m_identifiers, "put_by_id_replace");
802 break;
803 }
804 case op_put_by_id_transition: {
805 printPutByIdOp(location, it, m_identifiers, "put_by_id_transition");
806 break;
807 }
808 case op_put_by_id_generic: {
809 printPutByIdOp(location, it, m_identifiers, "put_by_id_generic");
810 break;
811 }
812 case op_put_getter: {
813 int r0 = (++it)->u.operand;
814 int id0 = (++it)->u.operand;
815 int r1 = (++it)->u.operand;
816 printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
817 break;
818 }
819 case op_put_setter: {
820 int r0 = (++it)->u.operand;
821 int id0 = (++it)->u.operand;
822 int r1 = (++it)->u.operand;
823 printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
824 break;
825 }
826 case op_del_by_id: {
827 int r0 = (++it)->u.operand;
828 int r1 = (++it)->u.operand;
829 int id0 = (++it)->u.operand;
830 printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str());
831 break;
832 }
833 case op_get_by_val: {
834 int r0 = (++it)->u.operand;
835 int r1 = (++it)->u.operand;
836 int r2 = (++it)->u.operand;
837 printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
838 break;
839 }
840 case op_put_by_val: {
841 int r0 = (++it)->u.operand;
842 int r1 = (++it)->u.operand;
843 int r2 = (++it)->u.operand;
844 printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
845 break;
846 }
847 case op_del_by_val: {
848 int r0 = (++it)->u.operand;
849 int r1 = (++it)->u.operand;
850 int r2 = (++it)->u.operand;
851 printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str());
852 break;
853 }
854 case op_put_by_index: {
855 int r0 = (++it)->u.operand;
856 unsigned n0 = (++it)->u.operand;
857 int r1 = (++it)->u.operand;
858 printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str());
859 break;
860 }
861 case op_jmp: {
862 int offset = (++it)->u.operand;
863 printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
864 break;
865 }
866 case op_loop: {
867 int offset = (++it)->u.operand;
868 printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset));
869 break;
870 }
871 case op_jtrue: {
872 printConditionalJump(begin, it, location, "jtrue");
873 break;
874 }
875 case op_loop_if_true: {
876 printConditionalJump(begin, it, location, "loop_if_true");
877 break;
878 }
879 case op_jfalse: {
880 printConditionalJump(begin, it, location, "jfalse");
881 break;
882 }
883 case op_jeq_null: {
884 printConditionalJump(begin, it, location, "jeq_null");
885 break;
886 }
887 case op_jneq_null: {
888 printConditionalJump(begin, it, location, "jneq_null");
889 break;
890 }
891 case op_jneq_ptr: {
892 int r0 = (++it)->u.operand;
893 int r1 = (++it)->u.operand;
894 int offset = (++it)->u.operand;
895 printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
896 break;
897 }
898 case op_jnless: {
899 int r0 = (++it)->u.operand;
900 JSValuePtr function = JSValuePtr((++it)->u.jsCell);
901 int offset = (++it)->u.operand;
902 printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), valueToSourceString(exec, function).ascii(), offset, locationForOffset(begin, it, offset));
903 break;
904 }
905 case op_loop_if_less: {
906 int r0 = (++it)->u.operand;
907 int r1 = (++it)->u.operand;
908 int offset = (++it)->u.operand;
909 printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
910 break;
911 }
912 case op_loop_if_lesseq: {
913 int r0 = (++it)->u.operand;
914 int r1 = (++it)->u.operand;
915 int offset = (++it)->u.operand;
916 printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset));
917 break;
918 }
919 case op_switch_imm: {
920 int tableIndex = (++it)->u.operand;
921 int defaultTarget = (++it)->u.operand;
922 int scrutineeRegister = (++it)->u.operand;
923 printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
924 break;
925 }
926 case op_switch_char: {
927 int tableIndex = (++it)->u.operand;
928 int defaultTarget = (++it)->u.operand;
929 int scrutineeRegister = (++it)->u.operand;
930 printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
931 break;
932 }
933 case op_switch_string: {
934 int tableIndex = (++it)->u.operand;
935 int defaultTarget = (++it)->u.operand;
936 int scrutineeRegister = (++it)->u.operand;
937 printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
938 break;
939 }
940 case op_new_func: {
941 int r0 = (++it)->u.operand;
942 int f0 = (++it)->u.operand;
943 printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0);
944 break;
945 }
946 case op_new_func_exp: {
947 int r0 = (++it)->u.operand;
948 int f0 = (++it)->u.operand;
949 printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0);
950 break;
951 }
952 case op_call: {
953 int dst = (++it)->u.operand;
954 int func = (++it)->u.operand;
955 int argCount = (++it)->u.operand;
956 int registerOffset = (++it)->u.operand;
957 printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
958 break;
959 }
960 case op_call_eval: {
961 int dst = (++it)->u.operand;
962 int func = (++it)->u.operand;
963 int argCount = (++it)->u.operand;
964 int registerOffset = (++it)->u.operand;
965 printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
966 break;
967 }
968 case op_call_varargs: {
969 int dst = (++it)->u.operand;
970 int func = (++it)->u.operand;
971 int argCount = (++it)->u.operand;
972 int registerOffset = (++it)->u.operand;
973 printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), registerName(argCount).c_str(), registerOffset);
974 break;
975 }
976 case op_load_varargs: {
977 printUnaryOp(location, it, "load_varargs");
978 break;
979 }
980 case op_tear_off_activation: {
981 int r0 = (++it)->u.operand;
982 printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str());
983 break;
984 }
985 case op_tear_off_arguments: {
986 printf("[%4d] tear_off_arguments\n", location);
987 break;
988 }
989 case op_ret: {
990 int r0 = (++it)->u.operand;
991 printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str());
992 break;
993 }
994 case op_construct: {
995 int dst = (++it)->u.operand;
996 int func = (++it)->u.operand;
997 int argCount = (++it)->u.operand;
998 int registerOffset = (++it)->u.operand;
999 int proto = (++it)->u.operand;
1000 int thisRegister = (++it)->u.operand;
1001 printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());
1002 break;
1003 }
1004 case op_construct_verify: {
1005 int r0 = (++it)->u.operand;
1006 int r1 = (++it)->u.operand;
1007 printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
1008 break;
1009 }
1010 case op_get_pnames: {
1011 int r0 = (++it)->u.operand;
1012 int r1 = (++it)->u.operand;
1013 printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str());
1014 break;
1015 }
1016 case op_next_pname: {
1017 int dest = (++it)->u.operand;
1018 int iter = (++it)->u.operand;
1019 int offset = (++it)->u.operand;
1020 printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset));
1021 break;
1022 }
1023 case op_push_scope: {
1024 int r0 = (++it)->u.operand;
1025 printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str());
1026 break;
1027 }
1028 case op_pop_scope: {
1029 printf("[%4d] pop_scope\n", location);
1030 break;
1031 }
1032 case op_push_new_scope: {
1033 int r0 = (++it)->u.operand;
1034 int id0 = (++it)->u.operand;
1035 int r1 = (++it)->u.operand;
1036 printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str());
1037 break;
1038 }
1039 case op_jmp_scopes: {
1040 int scopeDelta = (++it)->u.operand;
1041 int offset = (++it)->u.operand;
1042 printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset));
1043 break;
1044 }
1045 case op_catch: {
1046 int r0 = (++it)->u.operand;
1047 printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str());
1048 break;
1049 }
1050 case op_throw: {
1051 int r0 = (++it)->u.operand;
1052 printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str());
1053 break;
1054 }
1055 case op_new_error: {
1056 int r0 = (++it)->u.operand;
1057 int errorType = (++it)->u.operand;
1058 int k0 = (++it)->u.operand;
1059 printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str());
1060 break;
1061 }
1062 case op_jsr: {
1063 int retAddrDst = (++it)->u.operand;
1064 int offset = (++it)->u.operand;
1065 printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset));
1066 break;
1067 }
1068 case op_sret: {
1069 int retAddrSrc = (++it)->u.operand;
1070 printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str());
1071 break;
1072 }
1073 case op_debug: {
1074 int debugHookID = (++it)->u.operand;
1075 int firstLine = (++it)->u.operand;
1076 int lastLine = (++it)->u.operand;
1077 printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine);
1078 break;
1079 }
1080 case op_profile_will_call: {
1081 int function = (++it)->u.operand;
1082 printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str());
1083 break;
1084 }
1085 case op_profile_did_call: {
1086 int function = (++it)->u.operand;
1087 printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str());
1088 break;
1089 }
1090 case op_end: {
1091 int r0 = (++it)->u.operand;
1092 printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str());
1093 break;
1094 }
1095 }
1096}
1097
1098#endif // !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING)
1099
1100#if DUMP_CODE_BLOCK_STATISTICS
1101static HashSet<CodeBlock*> liveCodeBlockSet;
1102#endif
1103
1104#define FOR_EACH_MEMBER_VECTOR(macro) \
1105 macro(instructions) \
1106 macro(globalResolveInfos) \
1107 macro(structureStubInfos) \
1108 macro(callLinkInfos) \
1109 macro(linkedCallerList) \
1110 macro(identifiers) \
1111 macro(functionExpressions) \
1112 macro(constantRegisters)
1113
1114#define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \
1115 macro(regexps) \
1116 macro(functions) \
1117 macro(unexpectedConstants) \
1118 macro(exceptionHandlers) \
1119 macro(immediateSwitchJumpTables) \
1120 macro(characterSwitchJumpTables) \
1121 macro(stringSwitchJumpTables) \
1122 macro(functionRegisterInfos)
1123
1124#define FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(macro) \
1125 macro(expressionInfo) \
1126 macro(lineInfo) \
1127 macro(getByIdExceptionInfo) \
1128 macro(pcVector)
1129
1130template<typename T>
1131static size_t sizeInBytes(const Vector<T>& vector)
1132{
1133 return vector.capacity() * sizeof(T);
1134}
1135
1136void CodeBlock::dumpStatistics()
1137{
1138#if DUMP_CODE_BLOCK_STATISTICS
1139 #define DEFINE_VARS(name) size_t name##IsNotEmpty = 0; size_t name##TotalSize = 0;
1140 FOR_EACH_MEMBER_VECTOR(DEFINE_VARS)
1141 FOR_EACH_MEMBER_VECTOR_RARE_DATA(DEFINE_VARS)
1142 FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(DEFINE_VARS)
1143 #undef DEFINE_VARS
1144
1145 // Non-vector data members
1146 size_t evalCodeCacheIsNotEmpty = 0;
1147
1148 size_t symbolTableIsNotEmpty = 0;
1149 size_t symbolTableTotalSize = 0;
1150
1151 size_t hasExceptionInfo = 0;
1152 size_t hasRareData = 0;
1153
1154 size_t isFunctionCode = 0;
1155 size_t isGlobalCode = 0;
1156 size_t isEvalCode = 0;
1157
1158 HashSet<CodeBlock*>::const_iterator end = liveCodeBlockSet.end();
1159 for (HashSet<CodeBlock*>::const_iterator it = liveCodeBlockSet.begin(); it != end; ++it) {
1160 CodeBlock* codeBlock = *it;
1161
1162 #define GET_STATS(name) if (!codeBlock->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_##name); }
1163 FOR_EACH_MEMBER_VECTOR(GET_STATS)
1164 #undef GET_STATS
1165
1166 if (!codeBlock->m_symbolTable.isEmpty()) {
1167 symbolTableIsNotEmpty++;
1168 symbolTableTotalSize += (codeBlock->m_symbolTable.capacity() * (sizeof(SymbolTable::KeyType) + sizeof(SymbolTable::MappedType)));
1169 }
1170
1171 if (codeBlock->m_exceptionInfo) {
1172 hasExceptionInfo++;
1173 #define GET_STATS(name) if (!codeBlock->m_exceptionInfo->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_exceptionInfo->m_##name); }
1174 FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_STATS)
1175 #undef GET_STATS
1176 }
1177
1178 if (codeBlock->m_rareData) {
1179 hasRareData++;
1180 #define GET_STATS(name) if (!codeBlock->m_rareData->m_##name.isEmpty()) { name##IsNotEmpty++; name##TotalSize += sizeInBytes(codeBlock->m_rareData->m_##name); }
1181 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_STATS)
1182 #undef GET_STATS
1183
1184 if (!codeBlock->m_rareData->m_evalCodeCache.isEmpty())
1185 evalCodeCacheIsNotEmpty++;
1186 }
1187
1188 switch (codeBlock->codeType()) {
1189 case FunctionCode:
1190 ++isFunctionCode;
1191 break;
1192 case GlobalCode:
1193 ++isGlobalCode;
1194 break;
1195 case EvalCode:
1196 ++isEvalCode;
1197 break;
1198 }
1199 }
1200
1201 size_t totalSize = 0;
1202
1203 #define GET_TOTAL_SIZE(name) totalSize += name##TotalSize;
1204 FOR_EACH_MEMBER_VECTOR(GET_TOTAL_SIZE)
1205 FOR_EACH_MEMBER_VECTOR_RARE_DATA(GET_TOTAL_SIZE)
1206 FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(GET_TOTAL_SIZE)
1207 #undef GET_TOTAL_SIZE
1208
1209 totalSize += symbolTableTotalSize;
1210 totalSize += (liveCodeBlockSet.size() * sizeof(CodeBlock));
1211
1212 printf("Number of live CodeBlocks: %d\n", liveCodeBlockSet.size());
1213 printf("Size of a single CodeBlock [sizeof(CodeBlock)]: %zu\n", sizeof(CodeBlock));
1214 printf("Size of all CodeBlocks: %zu\n", totalSize);
1215 printf("Average size of a CodeBlock: %zu\n", totalSize / liveCodeBlockSet.size());
1216
1217 printf("Number of FunctionCode CodeBlocks: %zu (%.3f%%)\n", isFunctionCode, static_cast<double>(isFunctionCode) * 100.0 / liveCodeBlockSet.size());
1218 printf("Number of GlobalCode CodeBlocks: %zu (%.3f%%)\n", isGlobalCode, static_cast<double>(isGlobalCode) * 100.0 / liveCodeBlockSet.size());
1219 printf("Number of EvalCode CodeBlocks: %zu (%.3f%%)\n", isEvalCode, static_cast<double>(isEvalCode) * 100.0 / liveCodeBlockSet.size());
1220
1221 printf("Number of CodeBlocks with exception info: %zu (%.3f%%)\n", hasExceptionInfo, static_cast<double>(hasExceptionInfo) * 100.0 / liveCodeBlockSet.size());
1222 printf("Number of CodeBlocks with rare data: %zu (%.3f%%)\n", hasRareData, static_cast<double>(hasRareData) * 100.0 / liveCodeBlockSet.size());
1223
1224 #define PRINT_STATS(name) printf("Number of CodeBlocks with " #name ": %zu\n", name##IsNotEmpty); printf("Size of all " #name ": %zu\n", name##TotalSize);
1225 FOR_EACH_MEMBER_VECTOR(PRINT_STATS)
1226 FOR_EACH_MEMBER_VECTOR_RARE_DATA(PRINT_STATS)
1227 FOR_EACH_MEMBER_VECTOR_EXCEPTION_INFO(PRINT_STATS)
1228 #undef PRINT_STATS
1229
1230 printf("Number of CodeBlocks with evalCodeCache: %zu\n", evalCodeCacheIsNotEmpty);
1231 printf("Number of CodeBlocks with symbolTable: %zu\n", symbolTableIsNotEmpty);
1232
1233 printf("Size of all symbolTables: %zu\n", symbolTableTotalSize);
1234
1235#else
1236 printf("Dumping CodeBlock statistics is not enabled.\n");
1237#endif
1238}
1239
1240
1241CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset)
1242 : m_numCalleeRegisters(0)
1243 , m_numConstants(0)
1244 , m_numVars(0)
1245 , m_numParameters(0)
1246 , m_ownerNode(ownerNode)
1247 , m_globalData(0)
1248#ifndef NDEBUG
1249 , m_instructionCount(0)
1250#endif
1251 , m_needsFullScopeChain(ownerNode->needsActivation())
1252 , m_usesEval(ownerNode->usesEval())
1253 , m_isNumericCompareFunction(false)
1254 , m_codeType(codeType)
1255 , m_source(sourceProvider)
1256 , m_sourceOffset(sourceOffset)
1257 , m_exceptionInfo(new ExceptionInfo)
1258{
1259 ASSERT(m_source);
1260
1261#if DUMP_CODE_BLOCK_STATISTICS
1262 liveCodeBlockSet.add(this);
1263#endif
1264}
1265
1266CodeBlock::~CodeBlock()
1267{
1268#if !ENABLE(JIT)
1269 for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
1270 derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
1271
1272 for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
1273 derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
1274#else
1275 for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
1276 if (m_globalResolveInfos[i].structure)
1277 m_globalResolveInfos[i].structure->deref();
1278 }
1279
1280 for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
1281 m_structureStubInfos[i].deref();
1282
1283 for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
1284 CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
1285 if (callLinkInfo->isLinked())
1286 callLinkInfo->callee->removeCaller(callLinkInfo);
1287 }
1288
1289 unlinkCallers();
1290#endif
1291
1292#if DUMP_CODE_BLOCK_STATISTICS
1293 liveCodeBlockSet.remove(this);
1294#endif
1295}
1296
1297#if ENABLE(JIT)
1298void CodeBlock::unlinkCallers()
1299{
1300 size_t size = m_linkedCallerList.size();
1301 for (size_t i = 0; i < size; ++i) {
1302 CallLinkInfo* currentCaller = m_linkedCallerList[i];
1303 JIT::unlinkCall(currentCaller);
1304 currentCaller->setUnlinked();
1305 }
1306 m_linkedCallerList.clear();
1307}
1308#endif
1309
1310void CodeBlock::derefStructures(Instruction* vPC) const
1311{
1312 Interpreter* interpreter = m_globalData->interpreter;
1313
1314 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
1315 vPC[4].u.structure->deref();
1316 return;
1317 }
1318 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
1319 vPC[4].u.structure->deref();
1320 vPC[5].u.structure->deref();
1321 return;
1322 }
1323 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
1324 vPC[4].u.structure->deref();
1325 vPC[5].u.structureChain->deref();
1326 return;
1327 }
1328 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
1329 vPC[4].u.structure->deref();
1330 vPC[5].u.structure->deref();
1331 vPC[6].u.structureChain->deref();
1332 return;
1333 }
1334 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
1335 vPC[4].u.structure->deref();
1336 return;
1337 }
1338 if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
1339 if(vPC[4].u.structure)
1340 vPC[4].u.structure->deref();
1341 return;
1342 }
1343 if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
1344 || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {
1345 PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
1346 polymorphicStructures->derefStructures(vPC[5].u.operand);
1347 delete polymorphicStructures;
1348 return;
1349 }
1350
1351 // These instructions don't ref their Structures.
1352 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length));
1353}
1354
1355void CodeBlock::refStructures(Instruction* vPC) const
1356{
1357 Interpreter* interpreter = m_globalData->interpreter;
1358
1359 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
1360 vPC[4].u.structure->ref();
1361 return;
1362 }
1363 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
1364 vPC[4].u.structure->ref();
1365 vPC[5].u.structure->ref();
1366 return;
1367 }
1368 if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
1369 vPC[4].u.structure->ref();
1370 vPC[5].u.structureChain->ref();
1371 return;
1372 }
1373 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
1374 vPC[4].u.structure->ref();
1375 vPC[5].u.structure->ref();
1376 vPC[6].u.structureChain->ref();
1377 return;
1378 }
1379 if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_replace)) {
1380 vPC[4].u.structure->ref();
1381 return;
1382 }
1383
1384 // These instructions don't ref their Structures.
1385 ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic));
1386}
1387
1388void CodeBlock::mark()
1389{
1390 for (size_t i = 0; i < m_constantRegisters.size(); ++i)
1391 if (!m_constantRegisters[i].marked())
1392 m_constantRegisters[i].mark();
1393
1394 for (size_t i = 0; i < m_functionExpressions.size(); ++i)
1395 m_functionExpressions[i]->body()->mark();
1396
1397 if (m_rareData) {
1398 for (size_t i = 0; i < m_rareData->m_functions.size(); ++i)
1399 m_rareData->m_functions[i]->body()->mark();
1400
1401 for (size_t i = 0; i < m_rareData->m_unexpectedConstants.size(); ++i) {
1402 if (!m_rareData->m_unexpectedConstants[i].marked())
1403 m_rareData->m_unexpectedConstants[i].mark();
1404 }
1405 m_rareData->m_evalCodeCache.mark();
1406 }
1407}
1408
1409void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame)
1410{
1411 if (m_exceptionInfo)
1412 return;
1413
1414 ScopeChainNode* scopeChain = callFrame->scopeChain();
1415 if (m_needsFullScopeChain) {
1416 ScopeChain sc(scopeChain);
1417 int scopeDelta = sc.localDepth();
1418 if (m_codeType == EvalCode)
1419 scopeDelta -= static_cast<EvalCodeBlock*>(this)->baseScopeDepth();
1420 else if (m_codeType == FunctionCode)
1421 scopeDelta++; // Compilation of function code assumes activation is not on the scope chain yet.
1422 ASSERT(scopeDelta >= 0);
1423 while (scopeDelta--)
1424 scopeChain = scopeChain->next;
1425 }
1426
1427 switch (m_codeType) {
1428 case FunctionCode: {
1429 FunctionBodyNode* ownerFunctionBodyNode = static_cast<FunctionBodyNode*>(m_ownerNode);
1430 RefPtr<FunctionBodyNode> newFunctionBody = m_globalData->parser->reparse<FunctionBodyNode>(m_globalData, ownerFunctionBodyNode);
1431 ASSERT(newFunctionBody);
1432 newFunctionBody->finishParsing(ownerFunctionBodyNode->copyParameters(), ownerFunctionBodyNode->parameterCount());
1433
1434 m_globalData->scopeNodeBeingReparsed = newFunctionBody.get();
1435
1436 CodeBlock& newCodeBlock = newFunctionBody->bytecodeForExceptionInfoReparse(scopeChain, this);
1437 ASSERT(newCodeBlock.m_exceptionInfo);
1438 ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
1439
1440#if ENABLE(JIT)
1441 JIT::compile(m_globalData, &newCodeBlock);
1442 ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
1443#endif
1444
1445 m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
1446
1447 m_globalData->scopeNodeBeingReparsed = 0;
1448
1449 break;
1450 }
1451 case EvalCode: {
1452 EvalNode* ownerEvalNode = static_cast<EvalNode*>(m_ownerNode);
1453 RefPtr<EvalNode> newEvalBody = m_globalData->parser->reparse<EvalNode>(m_globalData, ownerEvalNode);
1454
1455 m_globalData->scopeNodeBeingReparsed = newEvalBody.get();
1456
1457 EvalCodeBlock& newCodeBlock = newEvalBody->bytecodeForExceptionInfoReparse(scopeChain, this);
1458 ASSERT(newCodeBlock.m_exceptionInfo);
1459 ASSERT(newCodeBlock.m_instructionCount == m_instructionCount);
1460
1461#if ENABLE(JIT)
1462 JIT::compile(m_globalData, &newCodeBlock);
1463 ASSERT(newCodeBlock.m_jitCode.codeSize == m_jitCode.codeSize);
1464#endif
1465
1466 m_exceptionInfo.set(newCodeBlock.m_exceptionInfo.release());
1467
1468 m_globalData->scopeNodeBeingReparsed = 0;
1469
1470 break;
1471 }
1472 default:
1473 // CodeBlocks for Global code blocks are transient and therefore to not gain from
1474 // from throwing out there exception information.
1475 ASSERT_NOT_REACHED();
1476 }
1477}
1478
1479HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset)
1480{
1481 ASSERT(bytecodeOffset < m_instructionCount);
1482
1483 if (!m_rareData)
1484 return 0;
1485
1486 Vector<HandlerInfo>& exceptionHandlers = m_rareData->m_exceptionHandlers;
1487 for (size_t i = 0; i < exceptionHandlers.size(); ++i) {
1488 // Handlers are ordered innermost first, so the first handler we encounter
1489 // that contains the source address is the correct handler to use.
1490 if (exceptionHandlers[i].start <= bytecodeOffset && exceptionHandlers[i].end >= bytecodeOffset)
1491 return &exceptionHandlers[i];
1492 }
1493
1494 return 0;
1495}
1496
1497int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset)
1498{
1499 ASSERT(bytecodeOffset < m_instructionCount);
1500
1501 reparseForExceptionInfoIfNecessary(callFrame);
1502 ASSERT(m_exceptionInfo);
1503
1504 if (!m_exceptionInfo->m_lineInfo.size())
1505 return m_ownerNode->source().firstLine(); // Empty function
1506
1507 int low = 0;
1508 int high = m_exceptionInfo->m_lineInfo.size();
1509 while (low < high) {
1510 int mid = low + (high - low) / 2;
1511 if (m_exceptionInfo->m_lineInfo[mid].instructionOffset <= bytecodeOffset)
1512 low = mid + 1;
1513 else
1514 high = mid;
1515 }
1516
1517 if (!low)
1518 return m_ownerNode->source().firstLine();
1519 return m_exceptionInfo->m_lineInfo[low - 1].lineNumber;
1520}
1521
1522int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset)
1523{
1524 ASSERT(bytecodeOffset < m_instructionCount);
1525
1526 reparseForExceptionInfoIfNecessary(callFrame);
1527 ASSERT(m_exceptionInfo);
1528
1529 if (!m_exceptionInfo->m_expressionInfo.size()) {
1530 // We didn't think anything could throw. Apparently we were wrong.
1531 startOffset = 0;
1532 endOffset = 0;
1533 divot = 0;
1534 return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
1535 }
1536
1537 int low = 0;
1538 int high = m_exceptionInfo->m_expressionInfo.size();
1539 while (low < high) {
1540 int mid = low + (high - low) / 2;
1541 if (m_exceptionInfo->m_expressionInfo[mid].instructionOffset <= bytecodeOffset)
1542 low = mid + 1;
1543 else
1544 high = mid;
1545 }
1546
1547 ASSERT(low);
1548 if (!low) {
1549 startOffset = 0;
1550 endOffset = 0;
1551 divot = 0;
1552 return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
1553 }
1554
1555 startOffset = m_exceptionInfo->m_expressionInfo[low - 1].startOffset;
1556 endOffset = m_exceptionInfo->m_expressionInfo[low - 1].endOffset;
1557 divot = m_exceptionInfo->m_expressionInfo[low - 1].divotPoint + m_sourceOffset;
1558 return lineNumberForBytecodeOffset(callFrame, bytecodeOffset);
1559}
1560
1561bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID)
1562{
1563 ASSERT(bytecodeOffset < m_instructionCount);
1564
1565 reparseForExceptionInfoIfNecessary(callFrame);
1566 ASSERT(m_exceptionInfo);
1567
1568 if (!m_exceptionInfo->m_getByIdExceptionInfo.size())
1569 return false;
1570
1571 int low = 0;
1572 int high = m_exceptionInfo->m_getByIdExceptionInfo.size();
1573 while (low < high) {
1574 int mid = low + (high - low) / 2;
1575 if (m_exceptionInfo->m_getByIdExceptionInfo[mid].bytecodeOffset <= bytecodeOffset)
1576 low = mid + 1;
1577 else
1578 high = mid;
1579 }
1580
1581 if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
1582 return false;
1583
1584 opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof;
1585 return true;
1586}
1587
1588#if ENABLE(JIT)
1589bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex)
1590{
1591 ASSERT(bytecodeOffset < m_instructionCount);
1592
1593 if (!m_rareData || !m_rareData->m_functionRegisterInfos.size())
1594 return false;
1595
1596 int low = 0;
1597 int high = m_rareData->m_functionRegisterInfos.size();
1598 while (low < high) {
1599 int mid = low + (high - low) / 2;
1600 if (m_rareData->m_functionRegisterInfos[mid].bytecodeOffset <= bytecodeOffset)
1601 low = mid + 1;
1602 else
1603 high = mid;
1604 }
1605
1606 if (!low || m_rareData->m_functionRegisterInfos[low - 1].bytecodeOffset != bytecodeOffset)
1607 return false;
1608
1609 functionRegisterIndex = m_rareData->m_functionRegisterInfos[low - 1].functionRegisterIndex;
1610 return true;
1611}
1612#endif
1613
1614#if !ENABLE(JIT)
1615bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset)
1616{
1617 if (m_globalResolveInstructions.isEmpty())
1618 return false;
1619
1620 int low = 0;
1621 int high = m_globalResolveInstructions.size();
1622 while (low < high) {
1623 int mid = low + (high - low) / 2;
1624 if (m_globalResolveInstructions[mid] <= bytecodeOffset)
1625 low = mid + 1;
1626 else
1627 high = mid;
1628 }
1629
1630 if (!low || m_globalResolveInstructions[low - 1] != bytecodeOffset)
1631 return false;
1632 return true;
1633}
1634#else
1635bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset)
1636{
1637 if (m_globalResolveInfos.isEmpty())
1638 return false;
1639
1640 int low = 0;
1641 int high = m_globalResolveInfos.size();
1642 while (low < high) {
1643 int mid = low + (high - low) / 2;
1644 if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset)
1645 low = mid + 1;
1646 else
1647 high = mid;
1648 }
1649
1650 if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset)
1651 return false;
1652 return true;
1653}
1654#endif
1655
1656#if ENABLE(JIT)
1657void CodeBlock::setJITCode(JITCodeRef& jitCode)
1658{
1659 m_jitCode = jitCode;
1660#if !ENABLE(OPCODE_SAMPLING)
1661 if (!BytecodeGenerator::dumpsGeneratedCode())
1662 m_instructions.clear();
1663#endif
1664}
1665#endif
1666
1667void CodeBlock::shrinkToFit()
1668{
1669 m_instructions.shrinkToFit();
1670
1671#if !ENABLE(JIT)
1672 m_propertyAccessInstructions.shrinkToFit();
1673 m_globalResolveInstructions.shrinkToFit();
1674#else
1675 m_structureStubInfos.shrinkToFit();
1676 m_globalResolveInfos.shrinkToFit();
1677 m_callLinkInfos.shrinkToFit();
1678 m_linkedCallerList.shrinkToFit();
1679#endif
1680
1681 m_identifiers.shrinkToFit();
1682 m_functionExpressions.shrinkToFit();
1683 m_constantRegisters.shrinkToFit();
1684
1685 if (m_exceptionInfo) {
1686 m_exceptionInfo->m_expressionInfo.shrinkToFit();
1687 m_exceptionInfo->m_lineInfo.shrinkToFit();
1688 m_exceptionInfo->m_getByIdExceptionInfo.shrinkToFit();
1689 }
1690
1691 if (m_rareData) {
1692 m_rareData->m_exceptionHandlers.shrinkToFit();
1693 m_rareData->m_functions.shrinkToFit();
1694 m_rareData->m_unexpectedConstants.shrinkToFit();
1695 m_rareData->m_regexps.shrinkToFit();
1696 m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
1697 m_rareData->m_characterSwitchJumpTables.shrinkToFit();
1698 m_rareData->m_stringSwitchJumpTables.shrinkToFit();
1699#if ENABLE(JIT)
1700 m_rareData->m_functionRegisterInfos.shrinkToFit();
1701#endif
1702 }
1703}
1704
1705} // namespace JSC
Note: See TracBrowser for help on using the repository browser.