code-stubs.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
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 36namespace v8 { 37namespace internal { 38 39bool CodeStub::FindCodeInCache(Code** code_out) { 40 int index = Heap::code_stubs()->FindEntry(GetKey()); 41 if (index != NumberDictionary::kNotFound) { 42 *code_out = Code::cast(Heap::code_stubs()->ValueAt(index)); 43 return true; 44 } 45 return false; 46} 47 48 49void CodeStub::GenerateCode(MacroAssembler* masm) { 50 // Update the static counter each time a new code stub is generated. 51 Counters::code_stubs.Increment(); 52 // Nested stubs are not allowed for leafs. 53 masm->set_allow_stub_calls(AllowsStubCalls()); 54 // Generate the code for the stub. 55 masm->set_generating_stub(true); 56 Generate(masm); 57} 58 59 60void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { 61 code->set_major_key(MajorKey()); 62 63 OPROFILE(CreateNativeCodeRegion(GetName(), 64 code->instruction_start(), 65 code->instruction_size())); 66 PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName())); 67 Counters::total_stubs_code_size.Increment(code->instruction_size()); 68 69#ifdef ENABLE_DISASSEMBLER 70 if (FLAG_print_code_stubs) { 71#ifdef DEBUG 72 Print(); 73#endif 74 code->Disassemble(GetName()); 75 PrintF("\n"); 76 } 77#endif 78} 79 80 81int CodeStub::GetCodeKind() { 82 return Code::STUB; 83} 84 85 86Handle<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( 101 static_cast<Code::Kind>(GetCodeKind()), 102 InLoop(), 103 GetICState()); 104 Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject()); 105 RecordCodeGeneration(*new_object, &masm); 106 107 // Update the dictionary and the root in Heap. 108 Handle<NumberDictionary> dict = 109 Factory::DictionaryAtNumberPut( 110 Handle<NumberDictionary>(Heap::code_stubs()), 111 GetKey(), 112 new_object); 113 Heap::public_set_code_stubs(*dict); 114 115 code = *new_object; 116 } 117 118 return Handle<Code>(code); 119} 120 121 122MaybeObject* CodeStub::TryGetCode() { 123 Code* code; 124 if (!FindCodeInCache(&code)) { 125 // Generate the new code. 126 MacroAssembler masm(NULL, 256); 127 GenerateCode(&masm); 128 129 // Create the code object. 130 CodeDesc desc; 131 masm.GetCode(&desc); 132 133 // Try to copy the generated code into a heap object. 134 Code::Flags flags = Code::ComputeFlags( 135 static_cast<Code::Kind>(GetCodeKind()), 136 InLoop(), 137 GetICState()); 138 Object* new_object; 139 { MaybeObject* maybe_new_object = 140 Heap::CreateCode(desc, flags, masm.CodeObject()); 141 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; 142 } 143 code = Code::cast(new_object); 144 RecordCodeGeneration(code, &masm); 145 146 // Try to update the code cache but do not fail if unable. 147 MaybeObject* maybe_new_object = 148 Heap::code_stubs()->AtNumberPut(GetKey(), code); 149 if (maybe_new_object->ToObject(&new_object)) { 150 Heap::public_set_code_stubs(NumberDictionary::cast(new_object)); 151 } 152 } 153 154 return code; 155} 156 157 158const char* CodeStub::MajorName(CodeStub::Major major_key, 159 bool allow_unknown_keys) { 160 switch (major_key) { 161#define DEF_CASE(name) case name: return #name; 162 CODE_STUB_LIST(DEF_CASE) 163#undef DEF_CASE 164 default: 165 if (!allow_unknown_keys) { 166 UNREACHABLE(); 167 } 168 return NULL; 169 } 170} 171 172 173} } // namespace v8::internal 174