| 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 |  * | 
| 8 |  * 1.  Redistributions of source code must retain the above copyright | 
| 9 |  *     notice, this list of conditions and the following disclaimer. | 
| 10 |  * 2.  Redistributions in binary form must reproduce the above copyright | 
| 11 |  *     notice, this list of conditions and the following disclaimer in the | 
| 12 |  *     documentation and/or other materials provided with the distribution. | 
| 13 |  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of | 
| 14 |  *     its contributors may be used to endorse or promote products derived | 
| 15 |  *     from this software without specific prior written permission. | 
| 16 |  * | 
| 17 |  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 
| 18 |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
| 19 |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
| 20 |  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 
| 21 |  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
| 22 |  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
| 23 |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
| 24 |  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 25 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
| 26 |  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 |  */ | 
| 28 |  | 
| 29 | #ifndef Instruction_h | 
| 30 | #define Instruction_h | 
| 31 |  | 
| 32 | #include "MacroAssembler.h" | 
| 33 | #include "Opcode.h" | 
| 34 | #include "Structure.h" | 
| 35 | #include "StructureChain.h" | 
| 36 | #include <wtf/VectorTraits.h> | 
| 37 |  | 
| 38 | #define POLYMORPHIC_LIST_CACHE_SIZE 8 | 
| 39 |  | 
| 40 | namespace JSC { | 
| 41 |  | 
| 42 |     // *Sigh*, If the JIT is enabled we need to track the stubRountine (of type CodeLocationLabel), | 
| 43 |     // If the JIT is not in use we don't actually need the variable (that said, if the JIT is not in use we don't | 
| 44 |     // curently actually use PolymorphicAccessStructureLists, which we should).  Anyway, this seems like the best | 
| 45 |     // solution for now - will need to something smarter if/when we actually want mixed-mode operation. | 
| 46 | #if ENABLE(JIT) | 
| 47 |     typedef CodeLocationLabel PolymorphicAccessStructureListStubRoutineType; | 
| 48 | #else | 
| 49 |     typedef void* PolymorphicAccessStructureListStubRoutineType; | 
| 50 | #endif | 
| 51 |  | 
| 52 |     class JSCell; | 
| 53 |     class Structure; | 
| 54 |     class StructureChain; | 
| 55 |  | 
| 56 |     // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream. | 
| 57 |     struct PolymorphicAccessStructureList : FastAllocBase { | 
| 58 |         struct PolymorphicStubInfo { | 
| 59 |             bool isChain; | 
| 60 |             PolymorphicAccessStructureListStubRoutineType stubRoutine; | 
| 61 |             Structure* base; | 
| 62 |             union { | 
| 63 |                 Structure* proto; | 
| 64 |                 StructureChain* chain; | 
| 65 |             } u; | 
| 66 |  | 
| 67 |             void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base) | 
| 68 |             { | 
| 69 |                 stubRoutine = _stubRoutine; | 
| 70 |                 base = _base; | 
| 71 |                 u.proto = 0; | 
| 72 |                 isChain = false; | 
| 73 |             } | 
| 74 |              | 
| 75 |             void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto) | 
| 76 |             { | 
| 77 |                 stubRoutine = _stubRoutine; | 
| 78 |                 base = _base; | 
| 79 |                 u.proto = _proto; | 
| 80 |                 isChain = false; | 
| 81 |             } | 
| 82 |              | 
| 83 |             void set(PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain) | 
| 84 |             { | 
| 85 |                 stubRoutine = _stubRoutine; | 
| 86 |                 base = _base; | 
| 87 |                 u.chain = _chain; | 
| 88 |                 isChain = true; | 
| 89 |             } | 
| 90 |         } list[POLYMORPHIC_LIST_CACHE_SIZE]; | 
| 91 |          | 
| 92 |         PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase) | 
| 93 |         { | 
| 94 |             list[0].set(stubRoutine: stubRoutine, base: firstBase); | 
| 95 |         } | 
| 96 |  | 
| 97 |         PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto) | 
| 98 |         { | 
| 99 |             list[0].set(stubRoutine: stubRoutine, base: firstBase, proto: firstProto); | 
| 100 |         } | 
| 101 |  | 
| 102 |         PolymorphicAccessStructureList(PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain) | 
| 103 |         { | 
| 104 |             list[0].set(stubRoutine: stubRoutine, base: firstBase, chain: firstChain); | 
| 105 |         } | 
| 106 |  | 
| 107 |         void derefStructures(int count) | 
| 108 |         { | 
| 109 |             for (int i = 0; i < count; ++i) { | 
| 110 |                 PolymorphicStubInfo& info = list[i]; | 
| 111 |  | 
| 112 |                 ASSERT(info.base); | 
| 113 |                 info.base->deref(); | 
| 114 |  | 
| 115 |                 if (info.u.proto) { | 
| 116 |                     if (info.isChain) | 
| 117 |                         info.u.chain->deref(); | 
| 118 |                     else | 
| 119 |                         info.u.proto->deref(); | 
| 120 |                 } | 
| 121 |             } | 
| 122 |         } | 
| 123 |     }; | 
| 124 |  | 
| 125 |     struct Instruction { | 
| 126 |         Instruction(Opcode opcode) | 
| 127 |         { | 
| 128 | #if !HAVE(COMPUTED_GOTO) | 
| 129 |             // We have to initialize one of the pointer members to ensure that | 
| 130 |             // the entire struct is initialized, when opcode is not a pointer. | 
| 131 |             u.jsCell = 0; | 
| 132 | #endif | 
| 133 |             u.opcode = opcode; | 
| 134 |         } | 
| 135 |  | 
| 136 |         Instruction(int operand) | 
| 137 |         { | 
| 138 |             // We have to initialize one of the pointer members to ensure that | 
| 139 |             // the entire struct is initialized in 64-bit. | 
| 140 |             u.jsCell = 0; | 
| 141 |             u.operand = operand; | 
| 142 |         } | 
| 143 |  | 
| 144 |         Instruction(Structure* structure) { u.structure = structure; } | 
| 145 |         Instruction(StructureChain* structureChain) { u.structureChain = structureChain; } | 
| 146 |         Instruction(JSCell* jsCell) { u.jsCell = jsCell; } | 
| 147 |         Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; } | 
| 148 |  | 
| 149 |         union { | 
| 150 |             Opcode opcode; | 
| 151 |             int operand; | 
| 152 |             Structure* structure; | 
| 153 |             StructureChain* structureChain; | 
| 154 |             JSCell* jsCell; | 
| 155 |             PolymorphicAccessStructureList* polymorphicStructures; | 
| 156 |         } u; | 
| 157 |     }; | 
| 158 |  | 
| 159 | } // namespace JSC | 
| 160 |  | 
| 161 | namespace WTF { | 
| 162 |  | 
| 163 |     template<> struct VectorTraits<JSC::Instruction> : VectorTraitsBase<true, JSC::Instruction> { }; | 
| 164 |  | 
| 165 | } // namespace WTF | 
| 166 |  | 
| 167 | #endif // Instruction_h | 
| 168 |  |