blob: d12def85efa03dd539341af65f32bec7349e2984 [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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"
Ben Murdoch257744e2011-11-30 15:57:28 +000032#include "stub-cache.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000033#include "factory.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010034#include "gdb-jit.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035#include "macro-assembler.h"
36
37namespace v8 {
38namespace internal {
39
Leon Clarkee46be812010-01-19 14:06:41 +000040bool CodeStub::FindCodeInCache(Code** code_out) {
Steve Block44f0eee2011-05-26 01:26:41 +010041 Heap* heap = Isolate::Current()->heap();
42 int index = heap->code_stubs()->FindEntry(GetKey());
Leon Clarkee46be812010-01-19 14:06:41 +000043 if (index != NumberDictionary::kNotFound) {
Steve Block44f0eee2011-05-26 01:26:41 +010044 *code_out = Code::cast(heap->code_stubs()->ValueAt(index));
Leon Clarkee46be812010-01-19 14:06:41 +000045 return true;
Steve Blockd0582a62009-12-15 09:54:21 +000046 }
Leon Clarkee46be812010-01-19 14:06:41 +000047 return false;
48}
Steve Blockd0582a62009-12-15 09:54:21 +000049
Leon Clarkee46be812010-01-19 14:06:41 +000050
51void CodeStub::GenerateCode(MacroAssembler* masm) {
52 // Update the static counter each time a new code stub is generated.
Steve Block44f0eee2011-05-26 01:26:41 +010053 masm->isolate()->counters()->code_stubs()->Increment();
Ben Murdoch086aeea2011-05-13 15:57:08 +010054
Leon Clarkee46be812010-01-19 14:06:41 +000055 // Nested stubs are not allowed for leafs.
Ben Murdoch086aeea2011-05-13 15:57:08 +010056 AllowStubCallsScope allow_scope(masm, AllowsStubCalls());
57
Leon Clarkee46be812010-01-19 14:06:41 +000058 // Generate the code for the stub.
59 masm->set_generating_stub(true);
60 Generate(masm);
61}
62
63
64void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
65 code->set_major_key(MajorKey());
66
Steve Block44f0eee2011-05-26 01:26:41 +010067 Isolate* isolate = masm->isolate();
68 PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
Ben Murdochb8e0da22011-05-16 14:20:40 +010069 GDBJIT(AddCode(GDBJITInterface::STUB, GetName(), code));
Steve Block44f0eee2011-05-26 01:26:41 +010070 Counters* counters = isolate->counters();
71 counters->total_stubs_code_size()->Increment(code->instruction_size());
Leon Clarkee46be812010-01-19 14:06:41 +000072
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() {
Steve Block44f0eee2011-05-26 01:26:41 +010091 Isolate* isolate = Isolate::Current();
92 Factory* factory = isolate->factory();
93 Heap* heap = isolate->heap();
Leon Clarkee46be812010-01-19 14:06:41 +000094 Code* code;
95 if (!FindCodeInCache(&code)) {
Steve Block44f0eee2011-05-26 01:26:41 +010096 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000097
Steve Blocka7e24c12009-10-30 11:49:00 +000098 // Generate the new code.
Ben Murdoch8b112d22011-06-08 16:22:53 +010099 MacroAssembler masm(isolate, NULL, 256);
Leon Clarkee46be812010-01-19 14:06:41 +0000100 GenerateCode(&masm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000101
102 // Create the code object.
103 CodeDesc desc;
104 masm.GetCode(&desc);
105
Leon Clarkee46be812010-01-19 14:06:41 +0000106 // Copy the generated code into a heap object.
Steve Block6ded16b2010-05-10 14:33:55 +0100107 Code::Flags flags = Code::ComputeFlags(
108 static_cast<Code::Kind>(GetCodeKind()),
109 InLoop(),
110 GetICState());
Steve Block44f0eee2011-05-26 01:26:41 +0100111 Handle<Code> new_object = factory->NewCode(
112 desc, flags, masm.CodeObject(), NeedsImmovableCode());
Leon Clarkee46be812010-01-19 14:06:41 +0000113 RecordCodeGeneration(*new_object, &masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100114 FinishCode(*new_object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000115
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800116 // Update the dictionary and the root in Heap.
117 Handle<NumberDictionary> dict =
Steve Block44f0eee2011-05-26 01:26:41 +0100118 factory->DictionaryAtNumberPut(
119 Handle<NumberDictionary>(heap->code_stubs()),
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800120 GetKey(),
121 new_object);
Steve Block44f0eee2011-05-26 01:26:41 +0100122 heap->public_set_code_stubs(*dict);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800123
Leon Clarkee46be812010-01-19 14:06:41 +0000124 code = *new_object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000125 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000126
Steve Block44f0eee2011-05-26 01:26:41 +0100127 ASSERT(!NeedsImmovableCode() || heap->lo_space()->Contains(code));
128 return Handle<Code>(code, isolate);
Leon Clarkee46be812010-01-19 14:06:41 +0000129}
130
131
John Reck59135872010-11-02 12:39:01 -0700132MaybeObject* CodeStub::TryGetCode() {
Leon Clarkee46be812010-01-19 14:06:41 +0000133 Code* code;
134 if (!FindCodeInCache(&code)) {
135 // Generate the new code.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100136 MacroAssembler masm(Isolate::Current(), NULL, 256);
Leon Clarkee46be812010-01-19 14:06:41 +0000137 GenerateCode(&masm);
Steve Block44f0eee2011-05-26 01:26:41 +0100138 Heap* heap = masm.isolate()->heap();
Leon Clarkee46be812010-01-19 14:06:41 +0000139
140 // Create the code object.
141 CodeDesc desc;
142 masm.GetCode(&desc);
143
144 // Try to copy the generated code into a heap object.
Steve Block6ded16b2010-05-10 14:33:55 +0100145 Code::Flags flags = Code::ComputeFlags(
146 static_cast<Code::Kind>(GetCodeKind()),
147 InLoop(),
148 GetICState());
John Reck59135872010-11-02 12:39:01 -0700149 Object* new_object;
150 { MaybeObject* maybe_new_object =
Steve Block44f0eee2011-05-26 01:26:41 +0100151 heap->CreateCode(desc, flags, masm.CodeObject());
John Reck59135872010-11-02 12:39:01 -0700152 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
153 }
Leon Clarkee46be812010-01-19 14:06:41 +0000154 code = Code::cast(new_object);
155 RecordCodeGeneration(code, &masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100156 FinishCode(code);
Leon Clarkee46be812010-01-19 14:06:41 +0000157
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800158 // Try to update the code cache but do not fail if unable.
159 MaybeObject* maybe_new_object =
Steve Block44f0eee2011-05-26 01:26:41 +0100160 heap->code_stubs()->AtNumberPut(GetKey(), code);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800161 if (maybe_new_object->ToObject(&new_object)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100162 heap->public_set_code_stubs(NumberDictionary::cast(new_object));
Leon Clarkee46be812010-01-19 14:06:41 +0000163 }
164 }
165
166 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000167}
168
169
Andrei Popescu31002712010-02-23 13:46:05 +0000170const char* CodeStub::MajorName(CodeStub::Major major_key,
171 bool allow_unknown_keys) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000172 switch (major_key) {
Steve Blockd0582a62009-12-15 09:54:21 +0000173#define DEF_CASE(name) case name: return #name;
174 CODE_STUB_LIST(DEF_CASE)
175#undef DEF_CASE
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 default:
Andrei Popescu31002712010-02-23 13:46:05 +0000177 if (!allow_unknown_keys) {
178 UNREACHABLE();
179 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 return NULL;
181 }
182}
183
184
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185int ICCompareStub::MinorKey() {
186 return OpField::encode(op_ - Token::EQ) | StateField::encode(state_);
187}
188
189
190void ICCompareStub::Generate(MacroAssembler* masm) {
191 switch (state_) {
192 case CompareIC::UNINITIALIZED:
193 GenerateMiss(masm);
194 break;
195 case CompareIC::SMIS:
196 GenerateSmis(masm);
197 break;
198 case CompareIC::HEAP_NUMBERS:
199 GenerateHeapNumbers(masm);
200 break;
Ben Murdoch257744e2011-11-30 15:57:28 +0000201 case CompareIC::STRINGS:
202 GenerateStrings(masm);
203 break;
204 case CompareIC::SYMBOLS:
205 GenerateSymbols(masm);
206 break;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100207 case CompareIC::OBJECTS:
208 GenerateObjects(masm);
209 break;
210 default:
211 UNREACHABLE();
212 }
213}
214
215
Ben Murdoch086aeea2011-05-13 15:57:08 +0100216const char* InstanceofStub::GetName() {
217 if (name_ != NULL) return name_;
218 const int kMaxNameLength = 100;
Steve Block44f0eee2011-05-26 01:26:41 +0100219 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
220 kMaxNameLength);
Ben Murdoch086aeea2011-05-13 15:57:08 +0100221 if (name_ == NULL) return "OOM";
222
223 const char* args = "";
224 if (HasArgsInRegisters()) {
225 args = "_REGS";
226 }
227
228 const char* inline_check = "";
229 if (HasCallSiteInlineCheck()) {
230 inline_check = "_INLINE";
231 }
232
233 const char* return_true_false_object = "";
234 if (ReturnTrueFalseObject()) {
235 return_true_false_object = "_TRUEFALSE";
236 }
237
238 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
239 "InstanceofStub%s%s%s",
240 args,
241 inline_check,
242 return_true_false_object);
243 return name_;
244}
245
246
Ben Murdoch257744e2011-11-30 15:57:28 +0000247void KeyedLoadFastElementStub::Generate(MacroAssembler* masm) {
248 KeyedLoadStubCompiler::GenerateLoadFastElement(masm);
249}
250
251
252void KeyedStoreFastElementStub::Generate(MacroAssembler* masm) {
253 KeyedStoreStubCompiler::GenerateStoreFastElement(masm, is_js_array_);
254}
255
256
257void KeyedLoadExternalArrayStub::Generate(MacroAssembler* masm) {
258 KeyedLoadStubCompiler::GenerateLoadExternalArray(masm, array_type_);
259}
260
261
262void KeyedStoreExternalArrayStub::Generate(MacroAssembler* masm) {
263 KeyedStoreStubCompiler::GenerateStoreExternalArray(masm, array_type_);
264}
265
266
Steve Blocka7e24c12009-10-30 11:49:00 +0000267} } // namespace v8::internal