code-stubs.cc revision b0fe1620dcb4135ac3ab2d66ff93072373911299
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 FinishCode(*new_object); 107 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 123MaybeObject* 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( 136 static_cast<Code::Kind>(GetCodeKind()), 137 InLoop(), 138 GetICState()); 139 Object* new_object; 140 { MaybeObject* maybe_new_object = 141 Heap::CreateCode(desc, flags, masm.CodeObject()); 142 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; 143 } 144 code = Code::cast(new_object); 145 RecordCodeGeneration(code, &masm); 146 FinishCode(code); 147 148 // Try to update the code cache but do not fail if unable. 149 MaybeObject* maybe_new_object = 150 Heap::code_stubs()->AtNumberPut(GetKey(), code); 151 if (maybe_new_object->ToObject(&new_object)) { 152 Heap::public_set_code_stubs(NumberDictionary::cast(new_object)); 153 } 154 } 155 156 return code; 157} 158 159 160const char* CodeStub::MajorName(CodeStub::Major major_key, 161 bool allow_unknown_keys) { 162 switch (major_key) { 163#define DEF_CASE(name) case name: return #name; 164 CODE_STUB_LIST(DEF_CASE) 165#undef DEF_CASE 166 default: 167 if (!allow_unknown_keys) { 168 UNREACHABLE(); 169 } 170 return NULL; 171 } 172} 173 174 175int ICCompareStub::MinorKey() { 176 return OpField::encode(op_ - Token::EQ) | StateField::encode(state_); 177} 178 179 180void ICCompareStub::Generate(MacroAssembler* masm) { 181 switch (state_) { 182 case CompareIC::UNINITIALIZED: 183 GenerateMiss(masm); 184 break; 185 case CompareIC::SMIS: 186 GenerateSmis(masm); 187 break; 188 case CompareIC::HEAP_NUMBERS: 189 GenerateHeapNumbers(masm); 190 break; 191 case CompareIC::OBJECTS: 192 GenerateObjects(masm); 193 break; 194 default: 195 UNREACHABLE(); 196 } 197} 198 199 200} } // namespace v8::internal 201