blob: 69f8477f89763c57c2c33bf3c975023f24966f30 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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"
Ben Murdochb8e0da22011-05-16 14:20:40 +010033#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000034#include "macro-assembler.h"
Andrei Popescu402d9372010-02-26 13:31:12 +000035#include "oprofile-agent.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37namespace v8 {
38namespace internal {
39
Leon Clarkee46be812010-01-19 14:06:41 +000040bool CodeStub::FindCodeInCache(Code** code_out) {
Leon Clarkee46be812010-01-19 14:06:41 +000041 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;
Steve Blockd0582a62009-12-15 09:54:21 +000045 }
Leon Clarkee46be812010-01-19 14:06:41 +000046 return false;
47}
Steve Blockd0582a62009-12-15 09:54:21 +000048
Leon Clarkee46be812010-01-19 14:06:41 +000049
50void CodeStub::GenerateCode(MacroAssembler* masm) {
51 // Update the static counter each time a new code stub is generated.
52 Counters::code_stubs.Increment();
Ben Murdoch086aeea2011-05-13 15:57:08 +010053
Leon Clarkee46be812010-01-19 14:06:41 +000054 // Nested stubs are not allowed for leafs.
Ben Murdoch086aeea2011-05-13 15:57:08 +010055 AllowStubCallsScope allow_scope(masm, AllowsStubCalls());
56
Leon Clarkee46be812010-01-19 14:06:41 +000057 // Generate the code for the stub.
58 masm->set_generating_stub(true);
59 Generate(masm);
60}
61
62
63void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
64 code->set_major_key(MajorKey());
65
Steve Block6ded16b2010-05-10 14:33:55 +010066 OPROFILE(CreateNativeCodeRegion(GetName(),
67 code->instruction_start(),
68 code->instruction_size()));
69 PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
Ben Murdochb8e0da22011-05-16 14:20:40 +010070 GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code));
Leon Clarkee46be812010-01-19 14:06:41 +000071 Counters::total_stubs_code_size.Increment(code->instruction_size());
72
73#ifdef ENABLE_DISASSEMBLER
74 if (FLAG_print_code_stubs) {
75#ifdef DEBUG
76 Print();
77#endif
78 code->Disassemble(GetName());
79 PrintF("\n");
80 }
81#endif
82}
83
84
Steve Block6ded16b2010-05-10 14:33:55 +010085int CodeStub::GetCodeKind() {
86 return Code::STUB;
87}
88
89
Leon Clarkee46be812010-01-19 14:06:41 +000090Handle<Code> CodeStub::GetCode() {
91 Code* code;
92 if (!FindCodeInCache(&code)) {
Steve Blockd0582a62009-12-15 09:54:21 +000093 v8::HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +000094
Steve Blocka7e24c12009-10-30 11:49:00 +000095 // Generate the new code.
96 MacroAssembler masm(NULL, 256);
Leon Clarkee46be812010-01-19 14:06:41 +000097 GenerateCode(&masm);
Steve Blocka7e24c12009-10-30 11:49:00 +000098
99 // Create the code object.
100 CodeDesc desc;
101 masm.GetCode(&desc);
102
Leon Clarkee46be812010-01-19 14:06:41 +0000103 // Copy the generated code into a heap object.
Steve Block6ded16b2010-05-10 14:33:55 +0100104 Code::Flags flags = Code::ComputeFlags(
105 static_cast<Code::Kind>(GetCodeKind()),
106 InLoop(),
107 GetICState());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100108 Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
Leon Clarkee46be812010-01-19 14:06:41 +0000109 RecordCodeGeneration(*new_object, &masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100110 FinishCode(*new_object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800112 // Update the dictionary and the root in Heap.
113 Handle<NumberDictionary> dict =
114 Factory::DictionaryAtNumberPut(
115 Handle<NumberDictionary>(Heap::code_stubs()),
116 GetKey(),
117 new_object);
118 Heap::public_set_code_stubs(*dict);
119
Leon Clarkee46be812010-01-19 14:06:41 +0000120 code = *new_object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000122
Leon Clarkee46be812010-01-19 14:06:41 +0000123 return Handle<Code>(code);
124}
125
126
John Reck59135872010-11-02 12:39:01 -0700127MaybeObject* CodeStub::TryGetCode() {
Leon Clarkee46be812010-01-19 14:06:41 +0000128 Code* code;
129 if (!FindCodeInCache(&code)) {
130 // Generate the new code.
131 MacroAssembler masm(NULL, 256);
132 GenerateCode(&masm);
133
134 // Create the code object.
135 CodeDesc desc;
136 masm.GetCode(&desc);
137
138 // Try to copy the generated code into a heap object.
Steve Block6ded16b2010-05-10 14:33:55 +0100139 Code::Flags flags = Code::ComputeFlags(
140 static_cast<Code::Kind>(GetCodeKind()),
141 InLoop(),
142 GetICState());
John Reck59135872010-11-02 12:39:01 -0700143 Object* new_object;
144 { MaybeObject* maybe_new_object =
145 Heap::CreateCode(desc, flags, masm.CodeObject());
146 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
147 }
Leon Clarkee46be812010-01-19 14:06:41 +0000148 code = Code::cast(new_object);
149 RecordCodeGeneration(code, &masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100150 FinishCode(code);
Leon Clarkee46be812010-01-19 14:06:41 +0000151
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800152 // Try to update the code cache but do not fail if unable.
153 MaybeObject* maybe_new_object =
154 Heap::code_stubs()->AtNumberPut(GetKey(), code);
155 if (maybe_new_object->ToObject(&new_object)) {
156 Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
Leon Clarkee46be812010-01-19 14:06:41 +0000157 }
158 }
159
160 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000161}
162
163
Andrei Popescu31002712010-02-23 13:46:05 +0000164const char* CodeStub::MajorName(CodeStub::Major major_key,
165 bool allow_unknown_keys) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 switch (major_key) {
Steve Blockd0582a62009-12-15 09:54:21 +0000167#define DEF_CASE(name) case name: return #name;
168 CODE_STUB_LIST(DEF_CASE)
169#undef DEF_CASE
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 default:
Andrei Popescu31002712010-02-23 13:46:05 +0000171 if (!allow_unknown_keys) {
172 UNREACHABLE();
173 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 return NULL;
175 }
176}
177
178
Ben Murdochb0fe1622011-05-05 13:52:32 +0100179int ICCompareStub::MinorKey() {
180 return OpField::encode(op_ - Token::EQ) | StateField::encode(state_);
181}
182
183
184void ICCompareStub::Generate(MacroAssembler* masm) {
185 switch (state_) {
186 case CompareIC::UNINITIALIZED:
187 GenerateMiss(masm);
188 break;
189 case CompareIC::SMIS:
190 GenerateSmis(masm);
191 break;
192 case CompareIC::HEAP_NUMBERS:
193 GenerateHeapNumbers(masm);
194 break;
195 case CompareIC::OBJECTS:
196 GenerateObjects(masm);
197 break;
198 default:
199 UNREACHABLE();
200 }
201}
202
203
Ben Murdoch086aeea2011-05-13 15:57:08 +0100204const char* InstanceofStub::GetName() {
205 if (name_ != NULL) return name_;
206 const int kMaxNameLength = 100;
207 name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
208 if (name_ == NULL) return "OOM";
209
210 const char* args = "";
211 if (HasArgsInRegisters()) {
212 args = "_REGS";
213 }
214
215 const char* inline_check = "";
216 if (HasCallSiteInlineCheck()) {
217 inline_check = "_INLINE";
218 }
219
220 const char* return_true_false_object = "";
221 if (ReturnTrueFalseObject()) {
222 return_true_false_object = "_TRUEFALSE";
223 }
224
225 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
226 "InstanceofStub%s%s%s",
227 args,
228 inline_check,
229 return_true_false_object);
230 return name_;
231}
232
233
Steve Blocka7e24c12009-10-30 11:49:00 +0000234} } // namespace v8::internal