Home | History | Annotate | Download | only in src
      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