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 "macro-assembler.h" 34 #include "oprofile-agent.h" 35 36 namespace v8 { 37 namespace internal { 38 39 bool CodeStub::FindCodeInCache(Code** code_out) { 40 if (has_custom_cache()) return GetCustomCache(code_out); 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 Counters::code_stubs.Increment(); 53 // Nested stubs are not allowed for leafs. 54 masm->set_allow_stub_calls(AllowsStubCalls()); 55 // Generate the code for the stub. 56 masm->set_generating_stub(true); 57 Generate(masm); 58 } 59 60 61 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { 62 code->set_major_key(MajorKey()); 63 64 #ifdef ENABLE_OPROFILE_AGENT 65 // Register the generated stub with the OPROFILE agent. 66 OProfileAgent::CreateNativeCodeRegion(GetName(), 67 code->instruction_start(), 68 code->instruction_size()); 69 #endif 70 71 LOG(CodeCreateEvent(Logger::STUB_TAG, code, GetName())); 72 Counters::total_stubs_code_size.Increment(code->instruction_size()); 73 74 #ifdef ENABLE_DISASSEMBLER 75 if (FLAG_print_code_stubs) { 76 #ifdef DEBUG 77 Print(); 78 #endif 79 code->Disassemble(GetName()); 80 PrintF("\n"); 81 } 82 #endif 83 } 84 85 86 Handle<Code> CodeStub::GetCode() { 87 Code* code; 88 if (!FindCodeInCache(&code)) { 89 v8::HandleScope scope; 90 91 // Generate the new code. 92 MacroAssembler masm(NULL, 256); 93 GenerateCode(&masm); 94 95 // Create the code object. 96 CodeDesc desc; 97 masm.GetCode(&desc); 98 99 // Copy the generated code into a heap object. 100 Code::Flags flags = Code::ComputeFlags(Code::STUB, InLoop()); 101 Handle<Code> new_object = 102 Factory::NewCode(desc, NULL, flags, masm.CodeObject()); 103 RecordCodeGeneration(*new_object, &masm); 104 105 if (has_custom_cache()) { 106 SetCustomCache(*new_object); 107 } else { 108 // Update the dictionary and the root in Heap. 109 Handle<NumberDictionary> dict = 110 Factory::DictionaryAtNumberPut( 111 Handle<NumberDictionary>(Heap::code_stubs()), 112 GetKey(), 113 new_object); 114 Heap::public_set_code_stubs(*dict); 115 } 116 code = *new_object; 117 } 118 119 return Handle<Code>(code); 120 } 121 122 123 Object* CodeStub::TryGetCode() { 124 Code* code; 125 if (!FindCodeInCache(&code)) { 126 // Generate the new code. 127 MacroAssembler masm(NULL, 256); 128 GenerateCode(&masm); 129 130 // Create the code object. 131 CodeDesc desc; 132 masm.GetCode(&desc); 133 134 // Try to copy the generated code into a heap object. 135 Code::Flags flags = Code::ComputeFlags(Code::STUB, InLoop()); 136 Object* new_object = 137 Heap::CreateCode(desc, NULL, flags, masm.CodeObject()); 138 if (new_object->IsFailure()) return new_object; 139 code = Code::cast(new_object); 140 RecordCodeGeneration(code, &masm); 141 142 if (has_custom_cache()) { 143 SetCustomCache(code); 144 } else { 145 // Try to update the code cache but do not fail if unable. 146 new_object = Heap::code_stubs()->AtNumberPut(GetKey(), code); 147 if (!new_object->IsFailure()) { 148 Heap::public_set_code_stubs(NumberDictionary::cast(new_object)); 149 } 150 } 151 } 152 153 return code; 154 } 155 156 157 const char* CodeStub::MajorName(CodeStub::Major major_key, 158 bool allow_unknown_keys) { 159 switch (major_key) { 160 #define DEF_CASE(name) case name: return #name; 161 CODE_STUB_LIST(DEF_CASE) 162 #undef DEF_CASE 163 default: 164 if (!allow_unknown_keys) { 165 UNREACHABLE(); 166 } 167 return NULL; 168 } 169 } 170 171 172 } } // namespace v8::internal 173