• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FindCodeInCache(Code ** code_out)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 
GenerateCode(MacroAssembler * masm)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 
RecordCodeGeneration(Code * code,MacroAssembler * masm)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 
GetCode()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 
TryGetCode()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 
MajorName(CodeStub::Major major_key,bool allow_unknown_keys)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