source: webkit/trunk/JavaScriptCore/VM/CTI.h@ 37682

Last change on this file since 37682 was 37681, checked in by Darin Adler, 17 years ago

JavaScriptCore:

2008-10-18 Darin Adler <Darin Adler>

Reviewed by Oliver Hunt.

Remove casts from JSValue* to derived classes, replacing them with
calls to inline casting functions. These functions are also a bit
better than aidrect cast because they also do a runtime assertion.

Removed use of 0 as for JSValue*, changing call sites to use a
noValue() function instead.

Move things needed by classes derived from JSValue out of the class,
since the classes won't be deriving from JSValue any more soon.

I did most of these changes by changing JSValue to not be JSValue* any
more, then fixing a lot of the compilation problems, then rolling out
the JSValue change.

1.011x as fast on SunSpider (presumably due to some of the Machine.cpp changes)

  • API/APICast.h: Removed unneeded forward declarations.
  • API/JSCallbackObject.h: Added an asCallbackObject function for casting.
  • API/JSCallbackObjectFunctions.h: (JSC::JSCallbackObject::asCallbackObject): Added. (JSC::JSCallbackObject::getOwnPropertySlot): Use asObject. (JSC::JSCallbackObject::call): Use noValue. (JSC::JSCallbackObject::staticValueGetter): Use asCallbackObject. (JSC::JSCallbackObject::staticFunctionGetter): Ditto. (JSC::JSCallbackObject::callbackGetter): Ditto.
  • JavaScriptCore.xcodeproj/project.pbxproj: Added RegExpMatchesArray.h.
  • VM/CTI.cpp: (JSC::CTI::asInteger): Added. For use casting a JSValue to an integer. (JSC::CTI::emitGetArg): Use asInteger. (JSC::CTI::emitGetPutArg): Ditto. (JSC::CTI::getConstantImmediateNumericArg): Ditto. Also use noValue. (JSC::CTI::emitInitRegister): Use asInteger. (JSC::CTI::getDeTaggedConstantImmediate): Ditto. (JSC::CTI::compileOpCallInitializeCallFrame): Ditto. (JSC::CTI::compileOpCall): Ditto. (JSC::CTI::compileOpStrictEq): Ditto. (JSC::CTI::privateCompileMainPass): Ditto. (JSC::CTI::privateCompileGetByIdProto): Ditto. (JSC::CTI::privateCompileGetByIdChain): Ditto. (JSC::CTI::privateCompilePutByIdTransition): Ditto.
  • VM/CTI.h: Rewrite the ARG-related macros to use C++ casts instead of C casts and get rid of some extra parentheses. Addd declaration of asInteger.
  • VM/CodeGenerator.cpp: (JSC::CodeGenerator::emitEqualityOp): Use asString. (JSC::CodeGenerator::emitLoad): Use noValue. (JSC::CodeGenerator::findScopedProperty): Change globalObject argument to JSObject* instead of JSValue*. (JSC::CodeGenerator::emitResolve): Remove unneeded cast. (JSC::CodeGenerator::emitGetScopedVar): Use asCell. (JSC::CodeGenerator::emitPutScopedVar): Ditto.
  • VM/CodeGenerator.h: Changed out argument of findScopedProperty. Also change the JSValueMap to use PtrHash explicitly instead of getting it from DefaultHash.
  • VM/JSPropertyNameIterator.cpp: (JSC::JSPropertyNameIterator::toPrimitive): Use noValue.
  • VM/JSPropertyNameIterator.h: (JSC::JSPropertyNameIterator::next): Ditto.
  • VM/Machine.cpp: (JSC::fastIsNumber): Moved isImmediate check here instead of checking for 0 inside Heap::isNumber. Use asCell and asNumberCell. (JSC::fastToInt32): Ditto. (JSC::fastToUInt32): Ditto. (JSC::jsLess): Use asString. (JSC::jsLessEq): Ditto. (JSC::jsAdd): Ditto. (JSC::jsTypeStringForValue): Use asObject. (JSC::jsIsObjectType): Ditto. (JSC::jsIsFunctionType): Ditto. (JSC::inlineResolveBase): Use noValue. (JSC::Machine::callEval): Use asString. Initialize result to undefined, not 0. (JSC::Machine::Machine): Remove unneeded casts to JSCell*. (JSC::Machine::throwException): Use asObject. (JSC::Machine::debug): Remove explicit calls to the DebuggerCallFrame constructor. (JSC::Machine::checkTimeout): Use noValue. (JSC::cachePrototypeChain): Use asObject. (JSC::Machine::tryCachePutByID): Use asCell. (JSC::Machine::tryCacheGetByID): Use aCell and asObject. (JSC::Machine::privateExecute): Use noValue, asCell, asObject, asString, asArray, asActivation, asFunction. Changed code that creates call frames for host functions to pass 0 for the function pointer -- the call frame needs a JSFunction* and a host function object is not one. This was caught by the assertions in the casting functions. Also remove some unneeded casts in cases where two values are compared. (JSC::Machine::retrieveLastCaller): Use noValue. (JSC::Machine::tryCTICachePutByID): Use asCell. (JSC::Machine::tryCTICacheGetByID): Use aCell and asObject. (JSC::setUpThrowTrampolineReturnAddress): Added this function to restore the PIC-branch-avoidance that was recently lost. (JSC::Machine::cti_op_add): Use asString. (JSC::Machine::cti_op_instanceof): Use asCell and asObject. (JSC::Machine::cti_op_call_JSFunction): Use asFunction. (JSC::Machine::cti_op_call_NotJSFunction): Changed code to pass 0 for the function pointer, since we don't have a JSFunction. Use asObject. (JSC::Machine::cti_op_tear_off_activation): Use asActivation. (JSC::Machine::cti_op_construct_JSConstruct): Use asFunction and asObject. (JSC::Machine::cti_op_construct_NotJSConstruct): use asObject. (JSC::Machine::cti_op_get_by_val): Use asArray and asString. (JSC::Machine::cti_op_resolve_func): Use asPointer; this helps prepare us for a situation where JSValue is not a pointer. (JSC::Machine::cti_op_put_by_val): Use asArray. (JSC::Machine::cti_op_put_by_val_array): Ditto. (JSC::Machine::cti_op_resolve_global): Use asGlobalObject. (JSC::Machine::cti_op_post_inc): Change VM_CHECK_EXCEPTION_2 to VM_CHECK_EXCEPTION_AT_END, since there's no observable work done after that point. Also use asPointer. (JSC::Machine::cti_op_resolve_with_base): Use asPointer. (JSC::Machine::cti_op_post_dec): Change VM_CHECK_EXCEPTION_2 to VM_CHECK_EXCEPTION_AT_END, since there's no observable work done after that point. Also use asPointer. (JSC::Machine::cti_op_call_eval): Use asObject, noValue, and change VM_CHECK_EXCEPTION_ARG to VM_THROW_EXCEPTION_AT_END. (JSC::Machine::cti_op_throw): Change return value to a JSValue*. (JSC::Machine::cti_op_in): Use asObject. (JSC::Machine::cti_op_switch_char): Use asString. (JSC::Machine::cti_op_switch_string): Ditto. (JSC::Machine::cti_op_put_getter): Use asObject. (JSC::Machine::cti_op_put_setter): Ditto. (JSC::Machine::cti_vm_throw): Change return value to a JSValue*. Use noValue.
  • VM/Machine.h: Change return values of both cti_op_throw and cti_vm_throw to JSValue*.
  • VM/Register.h: Remove nullJSValue, which is the same thing as noValue(). Also removed unneeded definition of JSValue.
  • kjs/ArgList.h: Removed unneeded definition of JSValue.
  • kjs/Arguments.h: (JSC::asArguments): Added.
  • kjs/ArrayPrototype.cpp: (JSC::getProperty): Use noValue. (JSC::arrayProtoFuncToString): Use asArray. (JSC::arrayProtoFuncToLocaleString): Ditto. (JSC::arrayProtoFuncConcat): Ditto. (JSC::arrayProtoFuncPop): Ditto. Also removed unneeded initialization of the result, which is set in both sides of the branch. (JSC::arrayProtoFuncPush): Ditto. (JSC::arrayProtoFuncShift): Removed unneeded initialization of the result, which is set in both sides of the branch. (JSC::arrayProtoFuncSort): Use asArray.
  • kjs/BooleanObject.h: (JSC::asBooleanObject): Added.
  • kjs/BooleanPrototype.cpp: (JSC::booleanProtoFuncToString): Use asBooleanObject. (JSC::booleanProtoFuncValueOf): Ditto.
  • kjs/CallData.cpp: (JSC::call): Use asObject and asFunction.
  • kjs/ConstructData.cpp: (JSC::construct): Ditto.
  • kjs/DateConstructor.cpp: (JSC::constructDate): Use asDateInstance.
  • kjs/DateInstance.h: (JSC::asDateInstance): Added.
  • kjs/DatePrototype.cpp: (JSC::dateProtoFuncToString): Use asDateInstance. (JSC::dateProtoFuncToUTCString): Ditto. (JSC::dateProtoFuncToDateString): Ditto. (JSC::dateProtoFuncToTimeString): Ditto. (JSC::dateProtoFuncToLocaleString): Ditto. (JSC::dateProtoFuncToLocaleDateString): Ditto. (JSC::dateProtoFuncToLocaleTimeString): Ditto. (JSC::dateProtoFuncValueOf): Ditto. (JSC::dateProtoFuncGetTime): Ditto. (JSC::dateProtoFuncGetFullYear): Ditto. (JSC::dateProtoFuncGetUTCFullYear): Ditto. (JSC::dateProtoFuncToGMTString): Ditto. (JSC::dateProtoFuncGetMonth): Ditto. (JSC::dateProtoFuncGetUTCMonth): Ditto. (JSC::dateProtoFuncGetDate): Ditto. (JSC::dateProtoFuncGetUTCDate): Ditto. (JSC::dateProtoFuncGetDay): Ditto. (JSC::dateProtoFuncGetUTCDay): Ditto. (JSC::dateProtoFuncGetHours): Ditto. (JSC::dateProtoFuncGetUTCHours): Ditto. (JSC::dateProtoFuncGetMinutes): Ditto. (JSC::dateProtoFuncGetUTCMinutes): Ditto. (JSC::dateProtoFuncGetSeconds): Ditto. (JSC::dateProtoFuncGetUTCSeconds): Ditto. (JSC::dateProtoFuncGetMilliSeconds): Ditto. (JSC::dateProtoFuncGetUTCMilliseconds): Ditto. (JSC::dateProtoFuncGetTimezoneOffset): Ditto. (JSC::dateProtoFuncSetTime): Ditto. (JSC::setNewValueFromTimeArgs): Ditto. (JSC::setNewValueFromDateArgs): Ditto. (JSC::dateProtoFuncSetYear): Ditto. (JSC::dateProtoFuncGetYear): Ditto.
  • kjs/DebuggerCallFrame.cpp: (JSC::DebuggerCallFrame::thisObject): Use asObject. (JSC::DebuggerCallFrame::evaluate): Use noValue.
  • kjs/DebuggerCallFrame.h: Added a constructor that takes only a callFrame.
  • kjs/ExecState.h: (JSC::ExecState::clearException): Use noValue.
  • kjs/FunctionPrototype.cpp: (JSC::functionProtoFuncToString): Use asFunction. (JSC::functionProtoFuncApply): Use asArguments and asArray.
  • kjs/GetterSetter.cpp: (JSC::GetterSetter::getPrimitiveNumber): Use noValue.
  • kjs/GetterSetter.h: (JSC::asGetterSetter): Added.
  • kjs/InternalFunction.cpp: (JSC::InternalFunction::name): Use asString.
  • kjs/InternalFunction.h: (JSC::asInternalFunction): Added.
  • kjs/JSActivation.cpp: (JSC::JSActivation::argumentsGetter): Use asActivation.
  • kjs/JSActivation.h: (JSC::asActivation): Added.
  • kjs/JSArray.cpp: (JSC::JSArray::putSlowCase): Use noValue. (JSC::JSArray::deleteProperty): Ditto. (JSC::JSArray::increaseVectorLength): Ditto. (JSC::JSArray::setLength): Ditto. (JSC::JSArray::pop): Ditto. (JSC::JSArray::sort): Ditto. (JSC::JSArray::compactForSorting): Ditto.
  • kjs/JSArray.h: (JSC::asArray): Added.
  • kjs/JSCell.cpp: (JSC::JSCell::getJSNumber): Use noValue.
  • kjs/JSCell.h: (JSC::asCell): Added. (JSC::JSValue::asCell): Changed to not preserve const. Given the wide use of JSValue* and JSCell*, it's not really useful to use const. (JSC::JSValue::isNumber): Use asValue. (JSC::JSValue::isString): Ditto. (JSC::JSValue::isGetterSetter): Ditto. (JSC::JSValue::isObject): Ditto. (JSC::JSValue::getNumber): Ditto. (JSC::JSValue::getString): Ditto. (JSC::JSValue::getObject): Ditto. (JSC::JSValue::getCallData): Ditto. (JSC::JSValue::getConstructData): Ditto. (JSC::JSValue::getUInt32): Ditto. (JSC::JSValue::getTruncatedInt32): Ditto. (JSC::JSValue::getTruncatedUInt32): Ditto. (JSC::JSValue::mark): Ditto. (JSC::JSValue::marked): Ditto. (JSC::JSValue::toPrimitive): Ditto. (JSC::JSValue::getPrimitiveNumber): Ditto. (JSC::JSValue::toBoolean): Ditto. (JSC::JSValue::toNumber): Ditto. (JSC::JSValue::toString): Ditto. (JSC::JSValue::toObject): Ditto. (JSC::JSValue::toThisObject): Ditto. (JSC::JSValue::needsThisConversion): Ditto. (JSC::JSValue::toThisString): Ditto. (JSC::JSValue::getJSNumber): Ditto.
  • kjs/JSFunction.cpp: (JSC::JSFunction::argumentsGetter): Use asFunction. (JSC::JSFunction::callerGetter): Ditto. (JSC::JSFunction::lengthGetter): Ditto. (JSC::JSFunction::construct): Use asObject.
  • kjs/JSFunction.h: (JSC::asFunction): Added.
  • kjs/JSGlobalObject.cpp: (JSC::lastInPrototypeChain): Use asObject.
  • kjs/JSGlobalObject.h: (JSC::asGlobalObject): Added. (JSC::ScopeChainNode::globalObject): Use asGlobalObject.
  • kjs/JSImmediate.h: Added noValue, asPointer, and makeValue functions. Use rawValue, makeValue, and noValue consistently instead of doing reinterpret_cast in various functions.
  • kjs/JSNumberCell.h: (JSC::asNumberCell): Added. (JSC::JSValue::uncheckedGetNumber): Use asValue and asNumberCell. (JSC::JSValue::toJSNumber): Use asValue.
  • kjs/JSObject.cpp: (JSC::JSObject::put): Use asObject and asGetterSetter. (JSC::callDefaultValueFunction): Use noValue. (JSC::JSObject::defineGetter): Use asGetterSetter. (JSC::JSObject::defineSetter): Ditto. (JSC::JSObject::lookupGetter): Ditto. Also use asObject. (JSC::JSObject::lookupSetter): Ditto. (JSC::JSObject::hasInstance): Use asObject. (JSC::JSObject::fillGetterPropertySlot): Use asGetterSetter.
  • kjs/JSObject.h: (JSC::JSObject::getDirect): Use noValue. (JSC::asObject): Added. (JSC::JSValue::isObject): Use asValue. (JSC::JSObject::get): Removed unneeded const_cast. (JSC::JSObject::getPropertySlot): Use asObject. (JSC::JSValue::get): Removed unneeded const_cast. Use asValue, asCell, and asObject. (JSC::JSValue::put): Ditto. (JSC::JSObject::allocatePropertyStorageInline): Fixed spelling of "oldPropertStorage".
  • kjs/JSString.cpp: (JSC::JSString::getOwnPropertySlot): Use asObject.
  • kjs/JSString.h: (JSC::asString): Added. (JSC::JSValue::toThisJSString): Use asValue.
  • kjs/JSValue.h: Make PreferredPrimitiveType a top level enum instead of a member of JSValue. Added an asValue function that returns this. Removed overload of asCell for const. Use asValue instead of getting right at this.
  • kjs/ObjectPrototype.cpp: (JSC::objectProtoFuncIsPrototypeOf): Use asObject. (JSC::objectProtoFuncDefineGetter): Ditto. (JSC::objectProtoFuncDefineSetter): Ditto.
  • kjs/PropertySlot.h: (JSC::PropertySlot::PropertySlot): Take a const JSValue* so the callers don't have to worry about const. (JSC::PropertySlot::clearBase): Use noValue. (JSC::PropertySlot::clearValue): Ditto.
  • kjs/RegExpConstructor.cpp: (JSC::regExpConstructorDollar1): Use asRegExpConstructor. (JSC::regExpConstructorDollar2): Ditto. (JSC::regExpConstructorDollar3): Ditto. (JSC::regExpConstructorDollar4): Ditto. (JSC::regExpConstructorDollar5): Ditto. (JSC::regExpConstructorDollar6): Ditto. (JSC::regExpConstructorDollar7): Ditto. (JSC::regExpConstructorDollar8): Ditto. (JSC::regExpConstructorDollar9): Ditto. (JSC::regExpConstructorInput): Ditto. (JSC::regExpConstructorMultiline): Ditto. (JSC::regExpConstructorLastMatch): Ditto. (JSC::regExpConstructorLastParen): Ditto. (JSC::regExpConstructorLeftContext): Ditto. (JSC::regExpConstructorRightContext): Ditto. (JSC::setRegExpConstructorInput): Ditto. (JSC::setRegExpConstructorMultiline): Ditto. (JSC::constructRegExp): Use asObject.
  • kjs/RegExpConstructor.h: (JSC::asRegExpConstructor): Added.
  • kjs/RegExpObject.cpp: (JSC::regExpObjectGlobal): Use asRegExpObject. (JSC::regExpObjectIgnoreCase): Ditto. (JSC::regExpObjectMultiline): Ditto. (JSC::regExpObjectSource): Ditto. (JSC::regExpObjectLastIndex): Ditto. (JSC::setRegExpObjectLastIndex): Ditto. (JSC::callRegExpObject): Ditto.
  • kjs/RegExpObject.h: (JSC::asRegExpObject): Added.
  • kjs/RegExpPrototype.cpp: (JSC::regExpProtoFuncTest): Use asRegExpObject. (JSC::regExpProtoFuncExec): Ditto. (JSC::regExpProtoFuncCompile): Ditto. (JSC::regExpProtoFuncToString): Ditto.
  • kjs/StringObject.h: (JSC::StringObject::internalValue): Use asString. (JSC::asStringObject): Added.
  • kjs/StringPrototype.cpp: (JSC::stringProtoFuncReplace): Use asRegExpObject. (JSC::stringProtoFuncToString): Ue asStringObject. (JSC::stringProtoFuncMatch): Use asRegExpObject. (JSC::stringProtoFuncSearch): Ditto. (JSC::stringProtoFuncSplit): Ditto.
  • kjs/StructureID.cpp: (JSC::StructureID::getEnumerablePropertyNames): Use asObject. (JSC::StructureID::createCachedPrototypeChain): Ditto. (JSC::StructureIDChain::StructureIDChain): Use asCell and asObject.
  • kjs/collector.h: (JSC::Heap::isNumber): Removed null handling. This can only be called on valid cells. (JSC::Heap::cellBlock): Removed overload for const and non-const. Whether the JSCell* is const or not really should have no effect on whether you can modify the collector block it's in.
  • kjs/interpreter.cpp: (JSC::Interpreter::evaluate): Use noValue and noObject.
  • kjs/nodes.cpp: (JSC::FunctionCallResolveNode::emitCode): Use JSObject for the global object rather than JSValue. (JSC::PostfixResolveNode::emitCode): Ditto. (JSC::PrefixResolveNode::emitCode): Ditto. (JSC::ReadModifyResolveNode::emitCode): Ditto. (JSC::AssignResolveNode::emitCode): Ditto.
  • kjs/operations.h: (JSC::equalSlowCaseInline): Use asString, asCell, asNumberCell, (JSC::strictEqualSlowCaseInline): Ditto.

WebCore:

2008-10-18 Darin Adler <Darin Adler>

Reviewed by Oliver Hunt.

Update for change to make PreferredPrimitiveType no longer
a member of JSValue.

  • bridge/c/c_instance.cpp: (JSC::Bindings::CInstance::defaultValue): Removed JSValue:: prefix.
  • bridge/jni/jni_instance.cpp: (JavaInstance::defaultValue): Ditto.
  • bridge/objc/objc_instance.mm: (ObjcInstance::defaultValue): Ditto.
  • bridge/qt/qt_instance.cpp: (JSC::Bindings::QtInstance::defaultValue): Ditto.
  • bridge/runtime.h: Ditto. Also removed typedef.
File size: 18.6 KB
Line 
1/*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef CTI_h
27#define CTI_h
28
29#if ENABLE(CTI)
30
31#define WTF_USE_CTI_REPATCH_PIC 1
32
33#include "Machine.h"
34#include "Opcode.h"
35#include "RegisterFile.h"
36#include <masm/X86Assembler.h>
37#include <profiler/Profiler.h>
38#include <wtf/AlwaysInline.h>
39#include <wtf/Vector.h>
40
41#define CTI_ARGS_code 0x0C
42#define CTI_ARGS_registerFile 0x0D
43#define CTI_ARGS_callFrame 0x0E
44#define CTI_ARGS_exception 0x0F
45#define CTI_ARGS_profilerReference 0x10
46#define CTI_ARGS_globalData 0x11
47
48#define ARG_callFrame static_cast<CallFrame*>(ARGS[CTI_ARGS_callFrame])
49#define ARG_registerFile static_cast<RegisterFile*>(ARGS[CTI_ARGS_registerFile])
50#define ARG_exception static_cast<JSValue**>(ARGS[CTI_ARGS_exception])
51#define ARG_profilerReference static_cast<Profiler**>(ARGS[CTI_ARGS_profilerReference])
52#define ARG_globalData static_cast<JSGlobalData*>(ARGS[CTI_ARGS_globalData])
53
54#define ARG_setCallFrame(newCallFrame) (ARGS[CTI_ARGS_callFrame] = (newCallFrame))
55
56#define ARG_src1 static_cast<JSValue*>(ARGS[1])
57#define ARG_src2 static_cast<JSValue*>(ARGS[2])
58#define ARG_src3 static_cast<JSValue*>(ARGS[3])
59#define ARG_src4 static_cast<JSValue*>(ARGS[4])
60#define ARG_src5 static_cast<JSValue*>(ARGS[5])
61#define ARG_id1 static_cast<Identifier*>(ARGS[1])
62#define ARG_id2 static_cast<Identifier*>(ARGS[2])
63#define ARG_id3 static_cast<Identifier*>(ARGS[3])
64#define ARG_id4 static_cast<Identifier*>(ARGS[4])
65#define ARG_int1 reinterpret_cast<intptr_t>(ARGS[1])
66#define ARG_int2 reinterpret_cast<intptr_t>(ARGS[2])
67#define ARG_int3 reinterpret_cast<intptr_t>(ARGS[3])
68#define ARG_int4 reinterpret_cast<intptr_t>(ARGS[4])
69#define ARG_int5 reinterpret_cast<intptr_t>(ARGS[5])
70#define ARG_int6 reinterpret_cast<intptr_t>(ARGS[6])
71#define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1])
72#define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1])
73#define ARG_registers1 static_cast<Register*>(ARGS[1])
74#define ARG_regexp1 static_cast<RegExp*>(ARGS[1])
75#define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1])
76#define ARG_instr1 static_cast<Instruction*>(ARGS[1])
77#define ARG_instr2 static_cast<Instruction*>(ARGS[2])
78#define ARG_instr3 static_cast<Instruction*>(ARGS[3])
79#define ARG_instr4 static_cast<Instruction*>(ARGS[4])
80#define ARG_instr5 static_cast<Instruction*>(ARGS[5])
81#define ARG_instr6 static_cast<Instruction*>(ARGS[6])
82
83#define CTI_RETURN_ADDRESS_SLOT (ARGS[-1])
84
85namespace JSC {
86
87 class CodeBlock;
88 class JSPropertyNameIterator;
89 class JSValue;
90 class Machine;
91 class Register;
92 class RegisterFile;
93 class ScopeChainNode;
94 class SimpleJumpTable;
95 class StringJumpTable;
96 class StructureIDChain;
97
98 struct Instruction;
99 struct OperandTypes;
100 struct StructureStubInfo;
101
102 typedef JSValue* (SFX_CALL *CTIHelper_j)(CTI_ARGS);
103 typedef JSPropertyNameIterator* (SFX_CALL *CTIHelper_p)(CTI_ARGS);
104 typedef void (SFX_CALL *CTIHelper_v)(CTI_ARGS);
105 typedef void* (SFX_CALL *CTIHelper_s)(CTI_ARGS);
106 typedef int (SFX_CALL *CTIHelper_b)(CTI_ARGS);
107 typedef VoidPtrPair (SFX_CALL *CTIHelper_2)(CTI_ARGS);
108
109 struct CallRecord {
110 X86Assembler::JmpSrc from;
111 void* to;
112 unsigned opcodeIndex;
113
114 CallRecord()
115 {
116 }
117
118 CallRecord(X86Assembler::JmpSrc f, CTIHelper_j t, unsigned i)
119 : from(f)
120 , to((void*)t)
121 , opcodeIndex(i)
122 {
123 }
124
125 CallRecord(X86Assembler::JmpSrc f, CTIHelper_p t, unsigned i)
126 : from(f)
127 , to((void*)t)
128 , opcodeIndex(i)
129 {
130 }
131
132 CallRecord(X86Assembler::JmpSrc f, CTIHelper_v t, unsigned i)
133 : from(f)
134 , to((void*)t)
135 , opcodeIndex(i)
136 {
137 }
138
139 CallRecord(X86Assembler::JmpSrc f, CTIHelper_s t, unsigned i)
140 : from(f)
141 , to((void*)t)
142 , opcodeIndex(i)
143 {
144 }
145
146 CallRecord(X86Assembler::JmpSrc f, CTIHelper_b t, unsigned i)
147 : from(f)
148 , to((void*)t)
149 , opcodeIndex(i)
150 {
151 }
152
153 CallRecord(X86Assembler::JmpSrc f, CTIHelper_2 t, unsigned i)
154 : from(f)
155 , to((void*)t)
156 , opcodeIndex(i)
157 {
158 }
159
160 CallRecord(X86Assembler::JmpSrc f, unsigned i)
161 : from(f)
162 , to(0)
163 , opcodeIndex(i)
164 {
165 }
166 };
167
168 struct JmpTable {
169 X86Assembler::JmpSrc from;
170 unsigned to;
171
172 JmpTable(X86Assembler::JmpSrc f, unsigned t)
173 : from(f)
174 , to(t)
175 {
176 }
177 };
178
179 struct SlowCaseEntry {
180 X86Assembler::JmpSrc from;
181 unsigned to;
182 unsigned hint;
183
184 SlowCaseEntry(X86Assembler::JmpSrc f, unsigned t, unsigned h = 0)
185 : from(f)
186 , to(t)
187 , hint(h)
188 {
189 }
190 };
191
192 struct SwitchRecord {
193 enum Type {
194 Immediate,
195 Character,
196 String
197 };
198
199 Type m_type;
200
201 union {
202 SimpleJumpTable* m_simpleJumpTable;
203 StringJumpTable* m_stringJumpTable;
204 } m_jumpTable;
205
206 unsigned m_opcodeIndex;
207 unsigned m_defaultOffset;
208
209 SwitchRecord(SimpleJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset, Type type)
210 : m_type(type)
211 , m_opcodeIndex(opcodeIndex)
212 , m_defaultOffset(defaultOffset)
213 {
214 m_jumpTable.m_simpleJumpTable = jumpTable;
215 }
216
217 SwitchRecord(StringJumpTable* jumpTable, unsigned opcodeIndex, unsigned defaultOffset)
218 : m_type(String)
219 , m_opcodeIndex(opcodeIndex)
220 , m_defaultOffset(defaultOffset)
221 {
222 m_jumpTable.m_stringJumpTable = jumpTable;
223 }
224 };
225
226 struct StructureStubCompilationInfo {
227 X86Assembler::JmpSrc callReturnLocation;
228 X86Assembler::JmpDst hotPathBegin;
229 X86Assembler::JmpSrc hotPathOther;
230 X86Assembler::JmpDst coldPathOther;
231 };
232
233 extern "C" {
234 JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*);
235 void ctiVMThrowTrampoline();
236 };
237
238 void ctiSetReturnAddress(void** where, void* what);
239 void ctiRepatchCallByReturnAddress(void* where, void* what);
240
241 class CTI {
242 static const int repatchGetByIdDefaultStructureID = -1;
243 // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler
244 // will compress the displacement, and we may not be able to fit a repatched offset.
245 static const int repatchGetByIdDefaultOffset = 256;
246
247#if USE(FAST_CALL_CTI_ARGUMENT)
248 static const int ctiArgumentInitSize = 2;
249#elif USE(CTI_ARGUMENT)
250 static const int ctiArgumentInitSize = 4;
251#else
252 static const int ctiArgumentInitSize = 0;
253#endif
254 // These architecture specific value are used to enable repatching - see comment on op_put_by_id.
255 static const int repatchOffsetPutByIdStructureID = 19;
256 static const int repatchOffsetPutByIdPropertyMapOffset = 34;
257 // These architecture specific value are used to enable repatching - see comment on op_get_by_id.
258 static const int repatchOffsetGetByIdStructureID = 19;
259 static const int repatchOffsetGetByIdBranchToSlowCase = 25;
260 static const int repatchOffsetGetByIdPropertyMapOffset = 34;
261#if ENABLE(SAMPLING_TOOL)
262 static const int repatchOffsetGetByIdSlowCaseCall = 27 + 4 + ctiArgumentInitSize;
263#else
264 static const int repatchOffsetGetByIdSlowCaseCall = 17 + 4 + ctiArgumentInitSize;
265#endif
266 static const int repatchOffsetOpCallCall = 6;
267
268 public:
269 static void compile(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock)
270 {
271 CTI cti(machine, callFrame, codeBlock);
272 cti.privateCompile();
273 }
274
275#if ENABLE(WREC)
276 static void* compileRegExp(Machine*, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase = false, bool multiline = false);
277#endif
278
279 static void compileGetByIdSelf(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress)
280 {
281 CTI cti(machine, callFrame, codeBlock);
282 cti.privateCompileGetByIdSelf(structureID, cachedOffset, returnAddress);
283 }
284
285 static void compileGetByIdProto(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress)
286 {
287 CTI cti(machine, callFrame, codeBlock);
288 cti.privateCompileGetByIdProto(structureID, prototypeStructureID, cachedOffset, returnAddress);
289 }
290
291 static void compileGetByIdChain(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
292 {
293 CTI cti(machine, callFrame, codeBlock);
294 cti.privateCompileGetByIdChain(structureID, chain, count, cachedOffset, returnAddress);
295 }
296
297 static void compilePutByIdReplace(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress)
298 {
299 CTI cti(machine, callFrame, codeBlock);
300 cti.privateCompilePutByIdReplace(structureID, cachedOffset, returnAddress);
301 }
302
303 static void compilePutByIdTransition(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC, void* returnAddress)
304 {
305 CTI cti(machine, callFrame, codeBlock);
306 cti.privateCompilePutByIdTransition(oldStructureID, newStructureID, cachedOffset, sIDC, returnAddress);
307 }
308
309 static void* compileArrayLengthTrampoline(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock)
310 {
311 CTI cti(machine, callFrame, codeBlock);
312 return cti.privateCompileArrayLengthTrampoline();
313 }
314
315 static void* compileStringLengthTrampoline(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock)
316 {
317 CTI cti(machine, callFrame, codeBlock);
318 return cti.privateCompileStringLengthTrampoline();
319 }
320
321 static void patchGetByIdSelf(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress);
322 static void patchPutByIdReplace(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress);
323
324 static void compilePatchGetArrayLength(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock, void* returnAddress)
325 {
326 CTI cti(machine, callFrame, codeBlock);
327 return cti.privateCompilePatchGetArrayLength(returnAddress);
328 }
329
330 static void linkCall(CodeBlock* callerCodeBlock, JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, void* returnAddress, int callerArgCount);
331 static void unlinkCall(StructureStubInfo*);
332
333 inline static JSValue* execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValue** exception)
334 {
335 return ctiTrampoline(code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData);
336 }
337
338 private:
339 CTI(Machine*, CallFrame*, CodeBlock*);
340
341 static uintptr_t asInteger(JSValue*);
342
343 bool isConstant(int src);
344 JSValue* getConstant(CallFrame*, int src);
345
346 void privateCompileMainPass();
347 void privateCompileLinkPass();
348 void privateCompileSlowCases();
349 void privateCompile();
350 void privateCompileGetByIdSelf(StructureID*, size_t cachedOffset, void* returnAddress);
351 void privateCompileGetByIdProto(StructureID*, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress);
352 void privateCompileGetByIdChain(StructureID*, StructureIDChain*, size_t count, size_t cachedOffset, void* returnAddress);
353 void privateCompilePutByIdReplace(StructureID*, size_t cachedOffset, void* returnAddress);
354 void privateCompilePutByIdTransition(StructureID*, StructureID*, size_t cachedOffset, StructureIDChain*, void* returnAddress);
355
356 void* privateCompileArrayLengthTrampoline();
357 void* privateCompileStringLengthTrampoline();
358 void privateCompilePatchGetArrayLength(void* returnAddress);
359
360 enum CompileOpCallType { OpCallNormal, OpCallEval, OpConstruct };
361 void compileOpCall(Instruction* instruction, unsigned i, unsigned structureIDInstructionIndex, CompileOpCallType type = OpCallNormal);
362 void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount);
363 void compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval);
364 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
365 void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type);
366 void putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2);
367 void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i);
368 void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi, unsigned i);
369
370 void emitGetArg(int src, X86Assembler::RegisterID dst);
371 void emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch);
372 void emitPutArg(X86Assembler::RegisterID src, unsigned offset);
373 void emitPutArgConstant(unsigned value, unsigned offset);
374 void emitPutResult(unsigned dst, X86Assembler::RegisterID from = X86::eax);
375
376 void emitInitRegister(unsigned dst);
377
378 void emitPutCTIParam(void* value, unsigned name);
379 void emitPutCTIParam(X86Assembler::RegisterID from, unsigned name);
380 void emitGetCTIParam(unsigned name, X86Assembler::RegisterID to);
381
382 void emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
383 void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to);
384
385 JSValue* getConstantImmediateNumericArg(unsigned src);
386 unsigned getDeTaggedConstantImmediate(JSValue* imm);
387
388 void emitJumpSlowCaseIfIsJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex);
389 void emitJumpSlowCaseIfNotJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex);
390
391 void emitJumpSlowCaseIfNotImmNum(X86Assembler::RegisterID, unsigned opcodeIndex);
392 void emitJumpSlowCaseIfNotImmNums(X86Assembler::RegisterID, X86Assembler::RegisterID, unsigned opcodeIndex);
393
394 void emitFastArithDeTagImmediate(X86Assembler::RegisterID);
395 X86Assembler::JmpSrc emitFastArithDeTagImmediateJumpIfZero(X86Assembler::RegisterID);
396 void emitFastArithReTagImmediate(X86Assembler::RegisterID);
397 void emitFastArithPotentiallyReTagImmediate(X86Assembler::RegisterID);
398 void emitFastArithImmToInt(X86Assembler::RegisterID);
399 void emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID, unsigned opcodeIndex);
400 void emitFastArithIntToImmNoCheck(X86Assembler::RegisterID);
401
402 void emitTagAsBoolImmediate(X86Assembler::RegisterID reg);
403
404 X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, X86::RegisterID);
405 X86Assembler::JmpSrc emitNakedCall(unsigned opcodeIndex, void(*function)());
406 X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_j);
407 X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_p);
408 X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_v);
409 X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_s);
410 X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_b);
411 X86Assembler::JmpSrc emitCTICall(unsigned opcodeIndex, CTIHelper_2);
412
413 void emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst);
414 void emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index);
415
416 void emitSlowScriptCheck(unsigned opcodeIndex);
417#ifndef NDEBUG
418 void printOpcodeOperandTypes(unsigned src1, unsigned src2);
419#endif
420
421 X86Assembler m_jit;
422 Machine* m_machine;
423 CallFrame* m_callFrame;
424 CodeBlock* m_codeBlock;
425
426 Vector<CallRecord> m_calls;
427 Vector<X86Assembler::JmpDst> m_labels;
428 Vector<StructureStubCompilationInfo> m_structureStubCompilationInfo;
429 Vector<JmpTable> m_jmpTable;
430
431 struct JSRInfo {
432 X86Assembler::JmpDst addrPosition;
433 X86Assembler::JmpDst target;
434
435 JSRInfo(const X86Assembler::JmpDst& storeLocation, const X86Assembler::JmpDst& targetLocation)
436 : addrPosition(storeLocation)
437 , target(targetLocation)
438 {
439 }
440 };
441
442 Vector<JSRInfo> m_jsrSites;
443 Vector<SlowCaseEntry> m_slowCases;
444 Vector<SwitchRecord> m_switches;
445
446 // This limit comes from the limit set in PCRE
447 static const int MaxPatternSize = (1 << 16);
448
449 };
450}
451
452#endif // ENABLE(CTI)
453
454#endif // CTI_h
Note: See TracBrowser for help on using the repository browser.