1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include "v8.h" 29 30 #include "bootstrapper.h" 31 #include "code-stubs.h" 32 #include "factory.h" 33 #include "gdb-jit.h" 34 #include "macro-assembler.h" 35 36 namespace v8 { 37 namespace internal { 38 39 bool CodeStub::FindCodeInCache(Code** code_out) { 40 Heap* heap = Isolate::Current()->heap(); 41 int index = heap->code_stubs()->FindEntry(GetKey()); 42 if (index != NumberDictionary::kNotFound) { 43 *code_out = Code::cast(heap->code_stubs()->ValueAt(index)); 44 return true; 45 } 46 return false; 47 } 48 49 50 void CodeStub::GenerateCode(MacroAssembler* masm) { 51 // Update the static counter each time a new code stub is generated. 52 masm->isolate()->counters()->code_stubs()->Increment(); 53 54 // Nested stubs are not allowed for leafs. 55 AllowStubCallsScope allow_scope(masm, AllowsStubCalls()); 56 57 // Generate the code for the stub. 58 masm->set_generating_stub(true); 59 Generate(masm); 60 } 61 62 63 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { 64 code->set_major_key(MajorKey()); 65 66 Isolate* isolate = masm->isolate(); 67 PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, GetName())); 68 GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code)); 69 Counters* counters = isolate->counters(); 70 counters->total_stubs_code_size()->Increment(code->instruction_size()); 71 72 #ifdef ENABLE_DISASSEMBLER 73 if (FLAG_print_code_stubs) { 74 #ifdef DEBUG 75 Print(); 76 #endif 77 code->Disassemble(GetName()); 78 PrintF("\n"); 79 } 80 #endif 81 } 82 83 84 int CodeStub::GetCodeKind() { 85 return Code::STUB; 86 } 87 88 89 Handle<Code> CodeStub::GetCode() { 90 Isolate* isolate = Isolate::Current(); 91 Factory* factory = isolate->factory(); 92 Heap* heap = isolate->heap(); 93 Code* code; 94 if (!FindCodeInCache(&code)) { 95 HandleScope scope(isolate); 96 97 // Generate the new code. 98 MacroAssembler masm(isolate, NULL, 256); 99 GenerateCode(&masm); 100 101 // Create the code object. 102 CodeDesc desc; 103 masm.GetCode(&desc); 104 105 // Copy the generated code into a heap object. 106 Code::Flags flags = Code::ComputeFlags( 107 static_cast<Code::Kind>(GetCodeKind()), 108 InLoop(), 109 GetICState()); 110 Handle<Code> new_object = factory->NewCode( 111 desc, flags, masm.CodeObject(), NeedsImmovableCode()); 112 RecordCodeGeneration(*new_object, &masm); 113 FinishCode(*new_object); 114 115 // Update the dictionary and the root in Heap. 116 Handle<NumberDictionary> dict = 117 factory->DictionaryAtNumberPut( 118 Handle<NumberDictionary>(heap->code_stubs()), 119 GetKey(), 120 new_object); 121 heap->public_set_code_stubs(*dict); 122 123 code = *new_object; 124 } 125 126 ASSERT(!NeedsImmovableCode() || heap->lo_space()->Contains(code)); 127 return Handle<Code>(code, isolate); 128 } 129 130 131 MaybeObject* CodeStub::TryGetCode() { 132 Code* code; 133 if (!FindCodeInCache(&code)) { 134 // Generate the new code. 135 MacroAssembler masm(Isolate::Current(), NULL, 256); 136 GenerateCode(&masm); 137 Heap* heap = masm.isolate()->heap(); 138 139 // Create the code object. 140 CodeDesc desc; 141 masm.GetCode(&desc); 142 143 // Try to copy the generated code into a heap object. 144 Code::Flags flags = Code::ComputeFlags( 145 static_cast<Code::Kind>(GetCodeKind()), 146 InLoop(), 147 GetICState()); 148 Object* new_object; 149 { MaybeObject* maybe_new_object = 150 heap->CreateCode(desc, flags, masm.CodeObject()); 151 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; 152 } 153 code = Code::cast(new_object); 154 RecordCodeGeneration(code, &masm); 155 FinishCode(code); 156 157 // Try to update the code cache but do not fail if unable. 158 MaybeObject* maybe_new_object = 159 heap->code_stubs()->AtNumberPut(GetKey(), code); 160 if (maybe_new_object->ToObject(&new_object)) { 161 heap->public_set_code_stubs(NumberDictionary::cast(new_object)); 162 } 163 } 164 165 return code; 166 } 167 168 169 const char* CodeStub::MajorName(CodeStub::Major major_key, 170 bool allow_unknown_keys) { 171 switch (major_key) { 172 #define DEF_CASE(name) case name: return #name; 173 CODE_STUB_LIST(DEF_CASE) 174 #undef DEF_CASE 175 default: 176 if (!allow_unknown_keys) { 177 UNREACHABLE(); 178 } 179 return NULL; 180 } 181 } 182 183 184 int ICCompareStub::MinorKey() { 185 return OpField::encode(op_ - Token::EQ) | StateField::encode(state_); 186 } 187 188 189 void ICCompareStub::Generate(MacroAssembler* masm) { 190 switch (state_) { 191 case CompareIC::UNINITIALIZED: 192 GenerateMiss(masm); 193 break; 194 case CompareIC::SMIS: 195 GenerateSmis(masm); 196 break; 197 case CompareIC::HEAP_NUMBERS: 198 GenerateHeapNumbers(masm); 199 break; 200 case CompareIC::OBJECTS: 201 GenerateObjects(masm); 202 break; 203 default: 204 UNREACHABLE(); 205 } 206 } 207 208 209 const char* InstanceofStub::GetName() { 210 if (name_ != NULL) return name_; 211 const int kMaxNameLength = 100; 212 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray( 213 kMaxNameLength); 214 if (name_ == NULL) return "OOM"; 215 216 const char* args = ""; 217 if (HasArgsInRegisters()) { 218 args = "_REGS"; 219 } 220 221 const char* inline_check = ""; 222 if (HasCallSiteInlineCheck()) { 223 inline_check = "_INLINE"; 224 } 225 226 const char* return_true_false_object = ""; 227 if (ReturnTrueFalseObject()) { 228 return_true_false_object = "_TRUEFALSE"; 229 } 230 231 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 232 "InstanceofStub%s%s%s", 233 args, 234 inline_check, 235 return_true_false_object); 236 return name_; 237 } 238 239 240 } } // namespace v8::internal 241