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