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 "gdb-jit.h"
34 #include "macro-assembler.h"
35
36 namespace v8 {
37 namespace internal {
38
FindCodeInCache(Code ** code_out)39 bool CodeStub::FindCodeInCache(Code** code_out) {
40 Heap* heap = Isolate::Current()->heap();
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 masm->isolate()->counters()->code_stubs()->Increment();
53
54 // Nested stubs are not allowed for leafs.
55 AllowStubCallsScope allow_scope(masm, AllowsStubCalls());
56
57 // Generate the code for the stub.
58 masm->set_generating_stub(true);
59 Generate(masm);
60 }
61
62
RecordCodeGeneration(Code * code,MacroAssembler * masm)63 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
64 code->set_major_key(MajorKey());
65
66 Isolate* isolate = masm->isolate();
67 PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
68 GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code));
69 Counters* counters = isolate->counters();
70 counters->total_stubs_code_size()->Increment(code->instruction_size());
71
72 #ifdef ENABLE_DISASSEMBLER
73 if (FLAG_print_code_stubs) {
74 #ifdef DEBUG
75 Print();
76 #endif
77 code->Disassemble(GetName());
78 PrintF("\n");
79 }
80 #endif
81 }
82
83
GetCodeKind()84 int CodeStub::GetCodeKind() {
85 return Code::STUB;
86 }
87
88
GetCode()89 Handle<Code> CodeStub::GetCode() {
90 Isolate* isolate = Isolate::Current();
91 Factory* factory = isolate->factory();
92 Heap* heap = isolate->heap();
93 Code* code;
94 if (!FindCodeInCache(&code)) {
95 HandleScope scope(isolate);
96
97 // Generate the new code.
98 MacroAssembler masm(isolate, NULL, 256);
99 GenerateCode(&masm);
100
101 // Create the code object.
102 CodeDesc desc;
103 masm.GetCode(&desc);
104
105 // Copy the generated code into a heap object.
106 Code::Flags flags = Code::ComputeFlags(
107 static_cast<Code::Kind>(GetCodeKind()),
108 InLoop(),
109 GetICState());
110 Handle<Code> new_object = factory->NewCode(
111 desc, flags, masm.CodeObject(), NeedsImmovableCode());
112 RecordCodeGeneration(*new_object, &masm);
113 FinishCode(*new_object);
114
115 // Update the dictionary and the root in Heap.
116 Handle<NumberDictionary> dict =
117 factory->DictionaryAtNumberPut(
118 Handle<NumberDictionary>(heap->code_stubs()),
119 GetKey(),
120 new_object);
121 heap->public_set_code_stubs(*dict);
122
123 code = *new_object;
124 }
125
126 ASSERT(!NeedsImmovableCode() || heap->lo_space()->Contains(code));
127 return Handle<Code>(code, isolate);
128 }
129
130
TryGetCode()131 MaybeObject* CodeStub::TryGetCode() {
132 Code* code;
133 if (!FindCodeInCache(&code)) {
134 // Generate the new code.
135 MacroAssembler masm(Isolate::Current(), NULL, 256);
136 GenerateCode(&masm);
137 Heap* heap = masm.isolate()->heap();
138
139 // Create the code object.
140 CodeDesc desc;
141 masm.GetCode(&desc);
142
143 // Try to copy the generated code into a heap object.
144 Code::Flags flags = Code::ComputeFlags(
145 static_cast<Code::Kind>(GetCodeKind()),
146 InLoop(),
147 GetICState());
148 Object* new_object;
149 { MaybeObject* maybe_new_object =
150 heap->CreateCode(desc, flags, masm.CodeObject());
151 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
152 }
153 code = Code::cast(new_object);
154 RecordCodeGeneration(code, &masm);
155 FinishCode(code);
156
157 // Try to update the code cache but do not fail if unable.
158 MaybeObject* maybe_new_object =
159 heap->code_stubs()->AtNumberPut(GetKey(), code);
160 if (maybe_new_object->ToObject(&new_object)) {
161 heap->public_set_code_stubs(NumberDictionary::cast(new_object));
162 }
163 }
164
165 return code;
166 }
167
168
MajorName(CodeStub::Major major_key,bool allow_unknown_keys)169 const char* CodeStub::MajorName(CodeStub::Major major_key,
170 bool allow_unknown_keys) {
171 switch (major_key) {
172 #define DEF_CASE(name) case name: return #name;
173 CODE_STUB_LIST(DEF_CASE)
174 #undef DEF_CASE
175 default:
176 if (!allow_unknown_keys) {
177 UNREACHABLE();
178 }
179 return NULL;
180 }
181 }
182
183
MinorKey()184 int ICCompareStub::MinorKey() {
185 return OpField::encode(op_ - Token::EQ) | StateField::encode(state_);
186 }
187
188
Generate(MacroAssembler * masm)189 void ICCompareStub::Generate(MacroAssembler* masm) {
190 switch (state_) {
191 case CompareIC::UNINITIALIZED:
192 GenerateMiss(masm);
193 break;
194 case CompareIC::SMIS:
195 GenerateSmis(masm);
196 break;
197 case CompareIC::HEAP_NUMBERS:
198 GenerateHeapNumbers(masm);
199 break;
200 case CompareIC::OBJECTS:
201 GenerateObjects(masm);
202 break;
203 default:
204 UNREACHABLE();
205 }
206 }
207
208
GetName()209 const char* InstanceofStub::GetName() {
210 if (name_ != NULL) return name_;
211 const int kMaxNameLength = 100;
212 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
213 kMaxNameLength);
214 if (name_ == NULL) return "OOM";
215
216 const char* args = "";
217 if (HasArgsInRegisters()) {
218 args = "_REGS";
219 }
220
221 const char* inline_check = "";
222 if (HasCallSiteInlineCheck()) {
223 inline_check = "_INLINE";
224 }
225
226 const char* return_true_false_object = "";
227 if (ReturnTrueFalseObject()) {
228 return_true_false_object = "_TRUEFALSE";
229 }
230
231 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
232 "InstanceofStub%s%s%s",
233 args,
234 inline_check,
235 return_true_false_object);
236 return name_;
237 }
238
239
240 } } // namespace v8::internal
241