OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 13 matching lines...) Expand all Loading... |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 | 28 |
29 #include "v8.h" | 29 #include "v8.h" |
30 | 30 |
31 #if defined(V8_TARGET_ARCH_MIPS) | 31 #if defined(V8_TARGET_ARCH_MIPS) |
32 | 32 |
33 #include "bootstrapper.h" | 33 #include "bootstrapper.h" |
| 34 #include "code-stubs.h" |
34 #include "codegen-inl.h" | 35 #include "codegen-inl.h" |
35 #include "compiler.h" | 36 #include "compiler.h" |
36 #include "debug.h" | 37 #include "debug.h" |
37 #include "ic-inl.h" | 38 #include "ic-inl.h" |
| 39 #include "jsregexp.h" |
| 40 #include "jump-target-inl.h" |
38 #include "parser.h" | 41 #include "parser.h" |
| 42 #include "regexp-macro-assembler.h" |
| 43 #include "regexp-stack.h" |
39 #include "register-allocator-inl.h" | 44 #include "register-allocator-inl.h" |
40 #include "runtime.h" | 45 #include "runtime.h" |
41 #include "scopes.h" | 46 #include "scopes.h" |
| 47 #include "stub-cache.h" |
42 #include "virtual-frame-inl.h" | 48 #include "virtual-frame-inl.h" |
43 | 49 #include "virtual-frame-mips-inl.h" |
44 | |
45 | 50 |
46 namespace v8 { | 51 namespace v8 { |
47 namespace internal { | 52 namespace internal { |
48 | 53 |
| 54 |
49 #define __ ACCESS_MASM(masm_) | 55 #define __ ACCESS_MASM(masm_) |
50 | 56 |
51 | 57 // ------------------------------------------------------------------------- |
52 | |
53 // ----------------------------------------------------------------------------- | |
54 // Platform-specific DeferredCode functions. | 58 // Platform-specific DeferredCode functions. |
55 | 59 |
56 | |
57 void DeferredCode::SaveRegisters() { | 60 void DeferredCode::SaveRegisters() { |
58 UNIMPLEMENTED_MIPS(); | 61 // On MIPS you either have a completely spilled frame or you |
| 62 // handle it yourself, but at the moment there's no automation |
| 63 // of registers and deferred code. |
59 } | 64 } |
60 | 65 |
61 | 66 |
62 void DeferredCode::RestoreRegisters() { | 67 void DeferredCode::RestoreRegisters() { |
63 UNIMPLEMENTED_MIPS(); | |
64 } | 68 } |
65 | 69 |
66 | 70 |
| 71 // ------------------------------------------------------------------------- |
| 72 // Platform-specific RuntimeCallHelper functions. |
| 73 |
| 74 void VirtualFrameRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { |
| 75 frame_state_->frame()->AssertIsSpilled(); |
| 76 } |
| 77 |
| 78 |
| 79 void VirtualFrameRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { |
| 80 } |
| 81 |
| 82 |
| 83 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { |
| 84 masm->EnterInternalFrame(); |
| 85 } |
| 86 |
| 87 |
| 88 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { |
| 89 masm->LeaveInternalFrame(); |
| 90 } |
| 91 |
| 92 |
67 // ----------------------------------------------------------------------------- | 93 // ----------------------------------------------------------------------------- |
68 // CodeGenState implementation. | 94 // CodeGenState implementation. |
69 | 95 |
70 CodeGenState::CodeGenState(CodeGenerator* owner) | 96 CodeGenState::CodeGenState(CodeGenerator* owner) |
71 : owner_(owner), | 97 : owner_(owner), |
72 true_target_(NULL), | 98 previous_(owner->state()) { |
73 false_target_(NULL), | 99 owner->set_state(this); |
74 previous_(NULL) { | |
75 owner_->set_state(this); | |
76 } | 100 } |
77 | 101 |
78 | 102 |
79 CodeGenState::CodeGenState(CodeGenerator* owner, | 103 ConditionCodeGenState::ConditionCodeGenState(CodeGenerator* owner, |
80 JumpTarget* true_target, | 104 JumpTarget* true_target, |
81 JumpTarget* false_target) | 105 JumpTarget* false_target) |
82 : owner_(owner), | 106 : CodeGenState(owner), |
83 true_target_(true_target), | 107 true_target_(true_target), |
84 false_target_(false_target), | 108 false_target_(false_target) { |
85 previous_(owner->state()) { | 109 owner->set_state(this); |
86 owner_->set_state(this); | |
87 } | 110 } |
88 | 111 |
89 | 112 |
| 113 TypeInfoCodeGenState::TypeInfoCodeGenState(CodeGenerator* owner, |
| 114 Slot* slot, |
| 115 TypeInfo type_info) |
| 116 : CodeGenState(owner), |
| 117 slot_(slot) { |
| 118 owner->set_state(this); |
| 119 old_type_info_ = owner->set_type_info(slot, type_info); |
| 120 } |
| 121 |
| 122 |
90 CodeGenState::~CodeGenState() { | 123 CodeGenState::~CodeGenState() { |
91 ASSERT(owner_->state() == this); | 124 ASSERT(owner_->state() == this); |
92 owner_->set_state(previous_); | 125 owner_->set_state(previous_); |
93 } | 126 } |
94 | 127 |
95 | 128 |
| 129 TypeInfoCodeGenState::~TypeInfoCodeGenState() { |
| 130 owner()->set_type_info(slot_, old_type_info_); |
| 131 } |
| 132 |
| 133 |
96 // ----------------------------------------------------------------------------- | 134 // ----------------------------------------------------------------------------- |
97 // CodeGenerator implementation | 135 // CodeGenerator implementation. |
98 | 136 |
99 CodeGenerator::CodeGenerator(MacroAssembler* masm) | 137 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
100 : deferred_(8), | 138 : deferred_(8), |
101 masm_(masm), | 139 masm_(masm), |
| 140 info_(NULL), |
102 frame_(NULL), | 141 frame_(NULL), |
103 allocator_(NULL), | 142 allocator_(NULL), |
104 cc_reg_(cc_always), | 143 cc_reg_(cc_always), |
105 state_(NULL), | 144 state_(NULL), |
| 145 loop_nesting_(0), |
| 146 type_info_(NULL), |
| 147 function_return_(JumpTarget::BIDIRECTIONAL), |
106 function_return_is_shadowed_(false) { | 148 function_return_is_shadowed_(false) { |
107 } | 149 } |
108 | 150 |
109 | 151 |
110 // Calling conventions: | 152 // Calling conventions: |
111 // fp: caller's frame pointer | 153 // fp: caller's frame pointer |
112 // sp: stack pointer | 154 // sp: stack pointer |
113 // a1: called JS function | 155 // a1: called JS function |
114 // cp: callee's context | 156 // cp: callee's context |
115 | 157 |
116 void CodeGenerator::Generate(CompilationInfo* info) { | 158 void CodeGenerator::Generate(CompilationInfo* info) { |
117 // Record the position for debugging purposes. | 159 UNIMPLEMENTED_MIPS(); |
118 CodeForFunctionPosition(info->function()); | 160 } |
119 | 161 |
120 // Initialize state. | 162 |
121 info_ = info; | 163 int CodeGenerator::NumberOfSlot(Slot* slot) { |
122 ASSERT(allocator_ == NULL); | 164 UNIMPLEMENTED_MIPS(); |
123 RegisterAllocator register_allocator(this); | 165 return 0; |
124 allocator_ = ®ister_allocator; | |
125 ASSERT(frame_ == NULL); | |
126 frame_ = new VirtualFrame(); | |
127 cc_reg_ = cc_always; | |
128 | |
129 { | |
130 CodeGenState state(this); | |
131 | |
132 // Registers: | |
133 // a1: called JS function | |
134 // ra: return address | |
135 // fp: caller's frame pointer | |
136 // sp: stack pointer | |
137 // cp: callee's context | |
138 // | |
139 // Stack: | |
140 // arguments | |
141 // receiver | |
142 | |
143 frame_->Enter(); | |
144 | |
145 // Allocate space for locals and initialize them. | |
146 frame_->AllocateStackSlots(); | |
147 | |
148 // Initialize the function return target. | |
149 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | |
150 function_return_is_shadowed_ = false; | |
151 | |
152 VirtualFrame::SpilledScope spilled_scope; | |
153 if (scope()->num_heap_slots() > 0) { | |
154 UNIMPLEMENTED_MIPS(); | |
155 } | |
156 | |
157 { | |
158 Comment cmnt2(masm_, "[ copy context parameters into .context"); | |
159 | |
160 // Note that iteration order is relevant here! If we have the same | |
161 // parameter twice (e.g., function (x, y, x)), and that parameter | |
162 // needs to be copied into the context, it must be the last argument | |
163 // passed to the parameter that needs to be copied. This is a rare | |
164 // case so we don't check for it, instead we rely on the copying | |
165 // order: such a parameter is copied repeatedly into the same | |
166 // context location and thus the last value is what is seen inside | |
167 // the function. | |
168 for (int i = 0; i < scope()->num_parameters(); i++) { | |
169 UNIMPLEMENTED_MIPS(); | |
170 } | |
171 } | |
172 | |
173 // Store the arguments object. This must happen after context | |
174 // initialization because the arguments object may be stored in the | |
175 // context. | |
176 if (scope()->arguments() != NULL) { | |
177 UNIMPLEMENTED_MIPS(); | |
178 } | |
179 | |
180 // Generate code to 'execute' declarations and initialize functions | |
181 // (source elements). In case of an illegal redeclaration we need to | |
182 // handle that instead of processing the declarations. | |
183 if (scope()->HasIllegalRedeclaration()) { | |
184 Comment cmnt(masm_, "[ illegal redeclarations"); | |
185 scope()->VisitIllegalRedeclaration(this); | |
186 } else { | |
187 Comment cmnt(masm_, "[ declarations"); | |
188 ProcessDeclarations(scope()->declarations()); | |
189 // Bail out if a stack-overflow exception occurred when processing | |
190 // declarations. | |
191 if (HasStackOverflow()) return; | |
192 } | |
193 | |
194 if (FLAG_trace) { | |
195 UNIMPLEMENTED_MIPS(); | |
196 } | |
197 | |
198 // Compile the body of the function in a vanilla state. Don't | |
199 // bother compiling all the code if the scope has an illegal | |
200 // redeclaration. | |
201 if (!scope()->HasIllegalRedeclaration()) { | |
202 Comment cmnt(masm_, "[ function body"); | |
203 #ifdef DEBUG | |
204 bool is_builtin = Isolate::Current()->bootstrapper()->IsActive(); | |
205 bool should_trace = | |
206 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | |
207 if (should_trace) { | |
208 UNIMPLEMENTED_MIPS(); | |
209 } | |
210 #endif | |
211 VisitStatementsAndSpill(info->function()->body()); | |
212 } | |
213 } | |
214 | |
215 if (has_valid_frame() || function_return_.is_linked()) { | |
216 if (!function_return_.is_linked()) { | |
217 CodeForReturnPosition(info->function()); | |
218 } | |
219 // Registers: | |
220 // v0: result | |
221 // sp: stack pointer | |
222 // fp: frame pointer | |
223 // cp: callee's context | |
224 | |
225 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | |
226 | |
227 function_return_.Bind(); | |
228 if (FLAG_trace) { | |
229 UNIMPLEMENTED_MIPS(); | |
230 } | |
231 | |
232 // Add a label for checking the size of the code used for returning. | |
233 Label check_exit_codesize; | |
234 masm_->bind(&check_exit_codesize); | |
235 | |
236 masm_->mov(sp, fp); | |
237 masm_->lw(fp, MemOperand(sp, 0)); | |
238 masm_->lw(ra, MemOperand(sp, 4)); | |
239 masm_->addiu(sp, sp, 8); | |
240 | |
241 // Here we use masm_-> instead of the __ macro to avoid the code coverage | |
242 // tool from instrumenting as we rely on the code size here. | |
243 // TODO(MIPS): Should we be able to use more than 0x1ffe parameters? | |
244 masm_->addiu(sp, sp, (scope()->num_parameters() + 1) * kPointerSize); | |
245 masm_->Jump(ra); | |
246 // The Jump automatically generates a nop in the branch delay slot. | |
247 | |
248 // Check that the size of the code used for returning matches what is | |
249 // expected by the debugger. | |
250 ASSERT_EQ(kJSReturnSequenceLength, | |
251 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | |
252 } | |
253 | |
254 // Code generation state must be reset. | |
255 ASSERT(!has_cc()); | |
256 ASSERT(state_ == NULL); | |
257 ASSERT(!function_return_is_shadowed_); | |
258 function_return_.Unuse(); | |
259 DeleteFrame(); | |
260 | |
261 // Process any deferred code using the register allocator. | |
262 if (!HasStackOverflow()) { | |
263 ProcessDeferred(); | |
264 } | |
265 | |
266 allocator_ = NULL; | |
267 } | |
268 | |
269 | |
270 void CodeGenerator::LoadReference(Reference* ref) { | |
271 VirtualFrame::SpilledScope spilled_scope; | |
272 Comment cmnt(masm_, "[ LoadReference"); | |
273 Expression* e = ref->expression(); | |
274 Property* property = e->AsProperty(); | |
275 Variable* var = e->AsVariableProxy()->AsVariable(); | |
276 | |
277 if (property != NULL) { | |
278 UNIMPLEMENTED_MIPS(); | |
279 } else if (var != NULL) { | |
280 // The expression is a variable proxy that does not rewrite to a | |
281 // property. Global variables are treated as named property references. | |
282 if (var->is_global()) { | |
283 LoadGlobal(); | |
284 ref->set_type(Reference::NAMED); | |
285 } else { | |
286 ASSERT(var->slot() != NULL); | |
287 ref->set_type(Reference::SLOT); | |
288 } | |
289 } else { | |
290 UNIMPLEMENTED_MIPS(); | |
291 } | |
292 } | |
293 | |
294 | |
295 void CodeGenerator::UnloadReference(Reference* ref) { | |
296 VirtualFrame::SpilledScope spilled_scope; | |
297 // Pop a reference from the stack while preserving TOS. | |
298 Comment cmnt(masm_, "[ UnloadReference"); | |
299 int size = ref->size(); | |
300 if (size > 0) { | |
301 frame_->EmitPop(a0); | |
302 frame_->Drop(size); | |
303 frame_->EmitPush(a0); | |
304 } | |
305 ref->set_unloaded(); | |
306 } | 166 } |
307 | 167 |
308 | 168 |
309 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 169 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { |
310 // Currently, this assertion will fail if we try to assign to | 170 UNIMPLEMENTED_MIPS(); |
311 // a constant variable that is constant because it is read-only | 171 return MemOperand(zero_reg, 0); |
312 // (such as the variable referring to a named function expression). | 172 } |
313 // We need to implement assignments to read-only variables. | 173 |
314 // Ideally, we should do this during AST generation (by converting | 174 |
315 // such assignments into expression statements); however, in general | 175 MemOperand CodeGenerator::ContextSlotOperandCheckExtensions( |
316 // we may not be able to make the decision until past AST generation, | 176 Slot* slot, |
317 // that is when the entire program is known. | 177 Register tmp, |
318 ASSERT(slot != NULL); | 178 Register tmp2, |
319 int index = slot->index(); | 179 JumpTarget* slow) { |
320 switch (slot->type()) { | 180 UNIMPLEMENTED_MIPS(); |
321 case Slot::PARAMETER: | 181 return MemOperand(zero_reg, 0); |
322 UNIMPLEMENTED_MIPS(); | 182 } |
323 return MemOperand(no_reg, 0); | 183 |
324 | 184 |
325 case Slot::LOCAL: | |
326 return frame_->LocalAt(index); | |
327 | |
328 case Slot::CONTEXT: { | |
329 UNIMPLEMENTED_MIPS(); | |
330 return MemOperand(no_reg, 0); | |
331 } | |
332 | |
333 default: | |
334 UNREACHABLE(); | |
335 return MemOperand(no_reg, 0); | |
336 } | |
337 } | |
338 | |
339 | |
340 // Loads a value on TOS. If it is a boolean value, the result may have been | |
341 // (partially) translated into branches, or it may have set the condition | |
342 // code register. If force_cc is set, the value is forced to set the | |
343 // condition code register and no value is pushed. If the condition code | |
344 // register was set, has_cc() is true and cc_reg_ contains the condition to | |
345 // test for 'true'. | |
346 void CodeGenerator::LoadCondition(Expression* x, | 185 void CodeGenerator::LoadCondition(Expression* x, |
347 JumpTarget* true_target, | 186 JumpTarget* true_target, |
348 JumpTarget* false_target, | 187 JumpTarget* false_target, |
349 bool force_cc) { | 188 bool force_cc) { |
350 ASSERT(!has_cc()); | 189 UNIMPLEMENTED_MIPS(); |
351 int original_height = frame_->height(); | 190 } |
352 | 191 |
353 { CodeGenState new_state(this, true_target, false_target); | 192 |
354 Visit(x); | 193 void CodeGenerator::Load(Expression* x) { |
355 | 194 UNIMPLEMENTED_MIPS(); |
356 // If we hit a stack overflow, we may not have actually visited | 195 } |
357 // the expression. In that case, we ensure that we have a | 196 |
358 // valid-looking frame state because we will continue to generate | 197 |
359 // code as we unwind the C++ stack. | 198 void CodeGenerator::LoadGlobal() { |
360 // | 199 UNIMPLEMENTED_MIPS(); |
361 // It's possible to have both a stack overflow and a valid frame | 200 } |
362 // state (eg, a subexpression overflowed, visiting it returned | 201 |
363 // with a dummied frame state, and visiting this expression | 202 |
364 // returned with a normal-looking state). | 203 void CodeGenerator::LoadGlobalReceiver(Register scratch) { |
365 if (HasStackOverflow() && | 204 UNIMPLEMENTED_MIPS(); |
366 has_valid_frame() && | 205 } |
367 !has_cc() && | 206 |
368 frame_->height() == original_height) { | 207 |
369 true_target->Jump(); | 208 ArgumentsAllocationMode CodeGenerator::ArgumentsMode() { |
370 } | 209 UNIMPLEMENTED_MIPS(); |
| 210 return EAGER_ARGUMENTS_ALLOCATION; |
| 211 } |
| 212 |
| 213 |
| 214 void CodeGenerator::StoreArgumentsObject(bool initial) { |
| 215 UNIMPLEMENTED_MIPS(); |
| 216 } |
| 217 |
| 218 |
| 219 void CodeGenerator::LoadTypeofExpression(Expression* x) { |
| 220 UNIMPLEMENTED_MIPS(); |
| 221 } |
| 222 |
| 223 |
| 224 Reference::Reference(CodeGenerator* cgen, |
| 225 Expression* expression, |
| 226 bool persist_after_get) |
| 227 : cgen_(cgen), |
| 228 expression_(expression), |
| 229 type_(ILLEGAL), |
| 230 persist_after_get_(persist_after_get) { |
| 231 UNIMPLEMENTED_MIPS(); |
| 232 } |
| 233 |
| 234 |
| 235 Reference::~Reference() { |
| 236 UNIMPLEMENTED_MIPS(); |
| 237 } |
| 238 |
| 239 |
| 240 void CodeGenerator::LoadReference(Reference* ref) { |
| 241 UNIMPLEMENTED_MIPS(); |
| 242 } |
| 243 |
| 244 |
| 245 void CodeGenerator::UnloadReference(Reference* ref) { |
| 246 UNIMPLEMENTED_MIPS(); |
| 247 } |
| 248 |
| 249 |
| 250 // ECMA-262, section 9.2, page 30: ToBoolean(). Convert the given |
| 251 // register to a boolean in the condition code register. The code |
| 252 // may jump to 'false_target' in case the register converts to 'false'. |
| 253 void CodeGenerator::ToBoolean(JumpTarget* true_target, |
| 254 JumpTarget* false_target) { |
| 255 UNIMPLEMENTED_MIPS(); |
| 256 } |
| 257 |
| 258 |
| 259 void CodeGenerator::GenericBinaryOperation(Token::Value op, |
| 260 OverwriteMode overwrite_mode, |
| 261 GenerateInlineSmi inline_smi, |
| 262 int constant_rhs) { |
| 263 UNIMPLEMENTED_MIPS(); |
| 264 } |
| 265 |
| 266 |
| 267 class DeferredInlineSmiOperation: public DeferredCode { |
| 268 public: |
| 269 DeferredInlineSmiOperation(Token::Value op, |
| 270 int value, |
| 271 bool reversed, |
| 272 OverwriteMode overwrite_mode, |
| 273 Register tos) |
| 274 : op_(op), |
| 275 value_(value), |
| 276 reversed_(reversed), |
| 277 overwrite_mode_(overwrite_mode), |
| 278 tos_register_(tos) { |
| 279 set_comment("[ DeferredInlinedSmiOperation"); |
371 } | 280 } |
372 if (force_cc && frame_ != NULL && !has_cc()) { | 281 |
373 // Convert the TOS value to a boolean in the condition code register. | 282 virtual void Generate(); |
374 UNIMPLEMENTED_MIPS(); | 283 // This stub makes explicit calls to SaveRegisters(), RestoreRegisters() and |
375 } | 284 // Exit(). Currently on MIPS SaveRegisters() and RestoreRegisters() are empty |
376 ASSERT(!force_cc || !has_valid_frame() || has_cc()); | 285 // methods, it is the responsibility of the deferred code to save and restore |
377 ASSERT(!has_valid_frame() || | 286 // registers. |
378 (has_cc() && frame_->height() == original_height) || | 287 virtual bool AutoSaveAndRestore() { return false; } |
379 (!has_cc() && frame_->height() == original_height + 1)); | 288 |
380 } | 289 void JumpToNonSmiInput(Condition cond, Register cmp1, const Operand& cmp2); |
381 | 290 void JumpToAnswerOutOfRange(Condition cond, |
382 | 291 Register cmp1, |
383 void CodeGenerator::Load(Expression* x) { | 292 const Operand& cmp2); |
384 #ifdef DEBUG | 293 |
385 int original_height = frame_->height(); | 294 private: |
386 #endif | 295 void GenerateNonSmiInput(); |
387 JumpTarget true_target; | 296 void GenerateAnswerOutOfRange(); |
388 JumpTarget false_target; | 297 void WriteNonSmiAnswer(Register answer, |
389 LoadCondition(x, &true_target, &false_target, false); | 298 Register heap_number, |
390 | 299 Register scratch); |
391 if (has_cc()) { | 300 |
392 UNIMPLEMENTED_MIPS(); | 301 Token::Value op_; |
393 } | 302 int value_; |
394 | 303 bool reversed_; |
395 if (true_target.is_linked() || false_target.is_linked()) { | 304 OverwriteMode overwrite_mode_; |
396 UNIMPLEMENTED_MIPS(); | 305 Register tos_register_; |
397 } | 306 Label non_smi_input_; |
398 ASSERT(has_valid_frame()); | 307 Label answer_out_of_range_; |
399 ASSERT(!has_cc()); | 308 }; |
400 ASSERT(frame_->height() == original_height + 1); | 309 |
401 } | 310 |
402 | 311 // For bit operations we try harder and handle the case where the input is not |
403 | 312 // a Smi but a 32bits integer without calling the generic stub. |
404 void CodeGenerator::LoadGlobal() { | 313 void DeferredInlineSmiOperation::JumpToNonSmiInput(Condition cond, |
405 VirtualFrame::SpilledScope spilled_scope; | 314 Register cmp1, |
406 __ lw(a0, GlobalObject()); | 315 const Operand& cmp2) { |
407 frame_->EmitPush(a0); | 316 UNIMPLEMENTED_MIPS(); |
408 } | 317 } |
409 | 318 |
410 | 319 |
411 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 320 // For bit operations the result is always 32bits so we handle the case where |
412 VirtualFrame::SpilledScope spilled_scope; | 321 // the result does not fit in a Smi without calling the generic stub. |
413 if (slot->type() == Slot::LOOKUP) { | 322 void DeferredInlineSmiOperation::JumpToAnswerOutOfRange(Condition cond, |
414 UNIMPLEMENTED_MIPS(); | 323 Register cmp1, |
415 } else { | 324 const Operand& cmp2) { |
416 __ lw(a0, SlotOperand(slot, a2)); | 325 UNIMPLEMENTED_MIPS(); |
417 frame_->EmitPush(a0); | 326 } |
418 if (slot->var()->mode() == Variable::CONST) { | 327 |
419 UNIMPLEMENTED_MIPS(); | 328 |
420 } | 329 // On entry the non-constant side of the binary operation is in tos_register_ |
421 } | 330 // and the constant smi side is nowhere. The tos_register_ is not used by the |
422 } | 331 // virtual frame. On exit the answer is in the tos_register_ and the virtual |
423 | 332 // frame is unchanged. |
424 | 333 void DeferredInlineSmiOperation::Generate() { |
425 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { | 334 UNIMPLEMENTED_MIPS(); |
426 ASSERT(slot != NULL); | 335 } |
427 if (slot->type() == Slot::LOOKUP) { | 336 |
428 UNIMPLEMENTED_MIPS(); | 337 |
429 } else { | 338 // Convert and write the integer answer into heap_number. |
430 ASSERT(!slot->var()->is_dynamic()); | 339 void DeferredInlineSmiOperation::WriteNonSmiAnswer(Register answer, |
431 | 340 Register heap_number, |
432 JumpTarget exit; | 341 Register scratch) { |
433 if (init_state == CONST_INIT) { | 342 UNIMPLEMENTED_MIPS(); |
434 UNIMPLEMENTED_MIPS(); | 343 } |
435 } | 344 |
436 | 345 |
437 // We must execute the store. Storing a variable must keep the | 346 void DeferredInlineSmiOperation::GenerateNonSmiInput() { |
438 // (new) value on the stack. This is necessary for compiling | 347 UNIMPLEMENTED_MIPS(); |
439 // assignment expressions. | 348 } |
440 // | 349 |
441 // Note: We will reach here even with slot->var()->mode() == | 350 |
442 // Variable::CONST because of const declarations which will | 351 void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() { |
443 // initialize consts to 'the hole' value and by doing so, end up | 352 UNIMPLEMENTED_MIPS(); |
444 // calling this code. a2 may be loaded with context; used below in | 353 } |
445 // RecordWrite. | 354 |
446 frame_->EmitPop(a0); | 355 |
447 __ sw(a0, SlotOperand(slot, a2)); | 356 void CodeGenerator::SmiOperation(Token::Value op, |
448 frame_->EmitPush(a0); | 357 Handle<Object> value, |
449 if (slot->type() == Slot::CONTEXT) { | 358 bool reversed, |
450 UNIMPLEMENTED_MIPS(); | 359 OverwriteMode mode) { |
451 } | 360 UNIMPLEMENTED_MIPS(); |
452 // If we definitely did not jump over the assignment, we do not need | 361 } |
453 // to bind the exit label. Doing so can defeat peephole | 362 |
454 // optimization. | 363 |
455 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { | 364 // On MIPS we load registers condReg1 and condReg2 with the values which should |
456 exit.Bind(); | 365 // be compared. With the CodeGenerator::cc_reg_ condition, functions will be |
457 } | 366 // able to evaluate correctly the condition. (eg CodeGenerator::Branch) |
458 } | 367 void CodeGenerator::Comparison(Condition cc, |
| 368 Expression* left, |
| 369 Expression* right, |
| 370 bool strict) { |
| 371 UNIMPLEMENTED_MIPS(); |
| 372 } |
| 373 |
| 374 |
| 375 void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args, |
| 376 CallFunctionFlags flags, |
| 377 int position) { |
| 378 UNIMPLEMENTED_MIPS(); |
| 379 } |
| 380 |
| 381 |
| 382 void CodeGenerator::CallApplyLazy(Expression* applicand, |
| 383 Expression* receiver, |
| 384 VariableProxy* arguments, |
| 385 int position) { |
| 386 UNIMPLEMENTED_MIPS(); |
| 387 } |
| 388 |
| 389 |
| 390 void CodeGenerator::Branch(bool if_true, JumpTarget* target) { |
| 391 UNIMPLEMENTED_MIPS(); |
| 392 } |
| 393 |
| 394 |
| 395 void CodeGenerator::CheckStack() { |
| 396 UNIMPLEMENTED_MIPS(); |
459 } | 397 } |
460 | 398 |
461 | 399 |
462 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 400 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
463 VirtualFrame::SpilledScope spilled_scope; | 401 UNIMPLEMENTED_MIPS(); |
464 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 402 } |
465 VisitAndSpill(statements->at(i)); | 403 |
466 } | 404 |
467 } | |
468 | |
469 | |
470 void CodeGenerator::VisitBlock(Block* node) { | 405 void CodeGenerator::VisitBlock(Block* node) { |
471 UNIMPLEMENTED_MIPS(); | 406 UNIMPLEMENTED_MIPS(); |
472 } | 407 } |
473 | 408 |
474 | 409 |
475 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 410 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
476 VirtualFrame::SpilledScope spilled_scope; | 411 UNIMPLEMENTED_MIPS(); |
477 frame_->EmitPush(cp); | |
478 __ li(t0, Operand(pairs)); | |
479 frame_->EmitPush(t0); | |
480 __ li(t0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); | |
481 frame_->EmitPush(t0); | |
482 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | |
483 // The result is discarded. | |
484 } | 412 } |
485 | 413 |
486 | 414 |
487 void CodeGenerator::VisitDeclaration(Declaration* node) { | 415 void CodeGenerator::VisitDeclaration(Declaration* node) { |
488 UNIMPLEMENTED_MIPS(); | 416 UNIMPLEMENTED_MIPS(); |
489 } | 417 } |
490 | 418 |
491 | 419 |
492 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 420 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
493 #ifdef DEBUG | 421 UNIMPLEMENTED_MIPS(); |
494 int original_height = frame_->height(); | |
495 #endif | |
496 VirtualFrame::SpilledScope spilled_scope; | |
497 Comment cmnt(masm_, "[ ExpressionStatement"); | |
498 CodeForStatementPosition(node); | |
499 Expression* expression = node->expression(); | |
500 expression->MarkAsStatement(); | |
501 LoadAndSpill(expression); | |
502 frame_->Drop(); | |
503 ASSERT(frame_->height() == original_height); | |
504 } | 422 } |
505 | 423 |
506 | 424 |
507 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 425 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
508 UNIMPLEMENTED_MIPS(); | 426 UNIMPLEMENTED_MIPS(); |
509 } | 427 } |
510 | 428 |
511 | 429 |
512 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 430 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
513 UNIMPLEMENTED_MIPS(); | 431 UNIMPLEMENTED_MIPS(); |
514 } | 432 } |
515 | 433 |
516 | 434 |
517 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 435 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
518 UNIMPLEMENTED_MIPS(); | 436 UNIMPLEMENTED_MIPS(); |
519 } | 437 } |
520 | 438 |
521 | 439 |
522 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 440 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
523 UNIMPLEMENTED_MIPS(); | 441 UNIMPLEMENTED_MIPS(); |
524 } | 442 } |
525 | 443 |
526 | 444 |
527 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 445 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
528 VirtualFrame::SpilledScope spilled_scope; | 446 UNIMPLEMENTED_MIPS(); |
529 Comment cmnt(masm_, "[ ReturnStatement"); | |
530 | |
531 CodeForStatementPosition(node); | |
532 LoadAndSpill(node->expression()); | |
533 if (function_return_is_shadowed_) { | |
534 frame_->EmitPop(v0); | |
535 function_return_.Jump(); | |
536 } else { | |
537 // Pop the result from the frame and prepare the frame for | |
538 // returning thus making it easier to merge. | |
539 frame_->EmitPop(v0); | |
540 frame_->PrepareForReturn(); | |
541 | |
542 function_return_.Jump(); | |
543 } | |
544 } | 447 } |
545 | 448 |
546 | 449 |
| 450 void CodeGenerator::GenerateReturnSequence() { |
| 451 UNIMPLEMENTED_MIPS(); |
| 452 } |
| 453 |
| 454 |
547 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 455 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
548 UNIMPLEMENTED_MIPS(); | 456 UNIMPLEMENTED_MIPS(); |
549 } | 457 } |
550 | 458 |
551 | 459 |
552 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 460 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
553 UNIMPLEMENTED_MIPS(); | 461 UNIMPLEMENTED_MIPS(); |
554 } | 462 } |
555 | 463 |
556 | 464 |
(...skipping 30 matching lines...) Expand all Loading... |
587 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { | 495 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { |
588 UNIMPLEMENTED_MIPS(); | 496 UNIMPLEMENTED_MIPS(); |
589 } | 497 } |
590 | 498 |
591 | 499 |
592 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 500 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
593 UNIMPLEMENTED_MIPS(); | 501 UNIMPLEMENTED_MIPS(); |
594 } | 502 } |
595 | 503 |
596 | 504 |
| 505 void CodeGenerator::InstantiateFunction( |
| 506 Handle<SharedFunctionInfo> function_info, |
| 507 bool pretenure) { |
| 508 UNIMPLEMENTED_MIPS(); |
| 509 } |
| 510 |
| 511 |
597 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 512 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
598 UNIMPLEMENTED_MIPS(); | 513 UNIMPLEMENTED_MIPS(); |
599 } | 514 } |
600 | 515 |
601 | 516 |
602 void CodeGenerator::VisitSharedFunctionInfoLiteral( | 517 void CodeGenerator::VisitSharedFunctionInfoLiteral( |
603 SharedFunctionInfoLiteral* node) { | 518 SharedFunctionInfoLiteral* node) { |
604 UNIMPLEMENTED_MIPS(); | 519 UNIMPLEMENTED_MIPS(); |
605 } | 520 } |
606 | 521 |
607 | 522 |
608 void CodeGenerator::VisitConditional(Conditional* node) { | 523 void CodeGenerator::VisitConditional(Conditional* node) { |
609 UNIMPLEMENTED_MIPS(); | 524 UNIMPLEMENTED_MIPS(); |
610 } | 525 } |
611 | 526 |
612 | 527 |
| 528 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
| 529 UNIMPLEMENTED_MIPS(); |
| 530 } |
| 531 |
| 532 |
| 533 void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot, |
| 534 TypeofState state) { |
| 535 UNIMPLEMENTED_MIPS(); |
| 536 } |
| 537 |
| 538 |
| 539 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { |
| 540 UNIMPLEMENTED_MIPS(); |
| 541 } |
| 542 |
| 543 |
| 544 void CodeGenerator::LoadFromGlobalSlotCheckExtensions(Slot* slot, |
| 545 TypeofState typeof_state, |
| 546 JumpTarget* slow) { |
| 547 UNIMPLEMENTED_MIPS(); |
| 548 } |
| 549 |
| 550 |
| 551 void CodeGenerator::EmitDynamicLoadFromSlotFastCase(Slot* slot, |
| 552 TypeofState typeof_state, |
| 553 JumpTarget* slow, |
| 554 JumpTarget* done) { |
| 555 UNIMPLEMENTED_MIPS(); |
| 556 } |
| 557 |
| 558 |
613 void CodeGenerator::VisitSlot(Slot* node) { | 559 void CodeGenerator::VisitSlot(Slot* node) { |
614 #ifdef DEBUG | 560 UNIMPLEMENTED_MIPS(); |
615 int original_height = frame_->height(); | |
616 #endif | |
617 VirtualFrame::SpilledScope spilled_scope; | |
618 Comment cmnt(masm_, "[ Slot"); | |
619 LoadFromSlot(node, typeof_state()); | |
620 ASSERT(frame_->height() == original_height + 1); | |
621 } | 561 } |
622 | 562 |
623 | 563 |
624 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { | 564 void CodeGenerator::VisitVariableProxy(VariableProxy* node) { |
625 #ifdef DEBUG | 565 UNIMPLEMENTED_MIPS(); |
626 int original_height = frame_->height(); | |
627 #endif | |
628 VirtualFrame::SpilledScope spilled_scope; | |
629 Comment cmnt(masm_, "[ VariableProxy"); | |
630 | |
631 Variable* var = node->var(); | |
632 Expression* expr = var->rewrite(); | |
633 if (expr != NULL) { | |
634 Visit(expr); | |
635 } else { | |
636 ASSERT(var->is_global()); | |
637 Reference ref(this, node); | |
638 ref.GetValueAndSpill(); | |
639 } | |
640 ASSERT(frame_->height() == original_height + 1); | |
641 } | 566 } |
642 | 567 |
643 | 568 |
644 void CodeGenerator::VisitLiteral(Literal* node) { | 569 void CodeGenerator::VisitLiteral(Literal* node) { |
645 #ifdef DEBUG | 570 UNIMPLEMENTED_MIPS(); |
646 int original_height = frame_->height(); | |
647 #endif | |
648 VirtualFrame::SpilledScope spilled_scope; | |
649 Comment cmnt(masm_, "[ Literal"); | |
650 __ li(t0, Operand(node->handle())); | |
651 frame_->EmitPush(t0); | |
652 ASSERT(frame_->height() == original_height + 1); | |
653 } | 571 } |
654 | 572 |
655 | 573 |
656 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 574 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
657 UNIMPLEMENTED_MIPS(); | 575 UNIMPLEMENTED_MIPS(); |
658 } | 576 } |
659 | 577 |
660 | 578 |
661 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 579 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
662 UNIMPLEMENTED_MIPS(); | 580 UNIMPLEMENTED_MIPS(); |
663 } | 581 } |
664 | 582 |
665 | 583 |
666 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 584 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
667 UNIMPLEMENTED_MIPS(); | 585 UNIMPLEMENTED_MIPS(); |
668 } | 586 } |
669 | 587 |
670 | 588 |
671 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 589 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
672 UNIMPLEMENTED_MIPS(); | 590 UNIMPLEMENTED_MIPS(); |
673 } | 591 } |
674 | 592 |
675 | 593 |
| 594 void CodeGenerator::EmitSlotAssignment(Assignment* node) { |
| 595 UNIMPLEMENTED_MIPS(); |
| 596 } |
| 597 |
| 598 |
| 599 void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) { |
| 600 UNIMPLEMENTED_MIPS(); |
| 601 } |
| 602 |
| 603 |
| 604 void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) { |
| 605 UNIMPLEMENTED_MIPS(); |
| 606 } |
| 607 |
| 608 |
676 void CodeGenerator::VisitAssignment(Assignment* node) { | 609 void CodeGenerator::VisitAssignment(Assignment* node) { |
677 #ifdef DEBUG | 610 UNIMPLEMENTED_MIPS(); |
678 int original_height = frame_->height(); | |
679 #endif | |
680 VirtualFrame::SpilledScope spilled_scope; | |
681 Comment cmnt(masm_, "[ Assignment"); | |
682 | |
683 { Reference target(this, node->target()); | |
684 if (target.is_illegal()) { | |
685 // Fool the virtual frame into thinking that we left the assignment's | |
686 // value on the frame. | |
687 frame_->EmitPush(zero_reg); | |
688 ASSERT(frame_->height() == original_height + 1); | |
689 return; | |
690 } | |
691 | |
692 if (node->op() == Token::ASSIGN || | |
693 node->op() == Token::INIT_VAR || | |
694 node->op() == Token::INIT_CONST) { | |
695 LoadAndSpill(node->value()); | |
696 } else { | |
697 UNIMPLEMENTED_MIPS(); | |
698 } | |
699 | |
700 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | |
701 if (var != NULL && | |
702 (var->mode() == Variable::CONST) && | |
703 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | |
704 // Assignment ignored - leave the value on the stack. | |
705 } else { | |
706 CodeForSourcePosition(node->position()); | |
707 if (node->op() == Token::INIT_CONST) { | |
708 // Dynamic constant initializations must use the function context | |
709 // and initialize the actual constant declared. Dynamic variable | |
710 // initializations are simply assignments and use SetValue. | |
711 target.SetValue(CONST_INIT); | |
712 } else { | |
713 target.SetValue(NOT_CONST_INIT); | |
714 } | |
715 } | |
716 } | |
717 ASSERT(frame_->height() == original_height + 1); | |
718 } | 611 } |
719 | 612 |
720 | 613 |
721 void CodeGenerator::VisitThrow(Throw* node) { | 614 void CodeGenerator::VisitThrow(Throw* node) { |
722 UNIMPLEMENTED_MIPS(); | 615 UNIMPLEMENTED_MIPS(); |
723 } | 616 } |
724 | 617 |
725 | 618 |
726 void CodeGenerator::VisitProperty(Property* node) { | 619 void CodeGenerator::VisitProperty(Property* node) { |
727 UNIMPLEMENTED_MIPS(); | 620 UNIMPLEMENTED_MIPS(); |
728 } | 621 } |
729 | 622 |
730 | 623 |
731 void CodeGenerator::VisitCall(Call* node) { | 624 void CodeGenerator::VisitCall(Call* node) { |
732 #ifdef DEBUG | 625 UNIMPLEMENTED_MIPS(); |
733 int original_height = frame_->height(); | |
734 #endif | |
735 VirtualFrame::SpilledScope spilled_scope; | |
736 Comment cmnt(masm_, "[ Call"); | |
737 | |
738 Expression* function = node->expression(); | |
739 ZoneList<Expression*>* args = node->arguments(); | |
740 | |
741 // Standard function call. | |
742 // Check if the function is a variable or a property. | |
743 Variable* var = function->AsVariableProxy()->AsVariable(); | |
744 Property* property = function->AsProperty(); | |
745 | |
746 // ------------------------------------------------------------------------ | |
747 // Fast-case: Use inline caching. | |
748 // --- | |
749 // According to ECMA-262, section 11.2.3, page 44, the function to call | |
750 // must be resolved after the arguments have been evaluated. The IC code | |
751 // automatically handles this by loading the arguments before the function | |
752 // is resolved in cache misses (this also holds for megamorphic calls). | |
753 // ------------------------------------------------------------------------ | |
754 | |
755 if (var != NULL && var->is_possibly_eval()) { | |
756 UNIMPLEMENTED_MIPS(); | |
757 } else if (var != NULL && !var->is_this() && var->is_global()) { | |
758 // ---------------------------------- | |
759 // JavaScript example: 'foo(1, 2, 3)' // foo is global | |
760 // ---------------------------------- | |
761 | |
762 int arg_count = args->length(); | |
763 | |
764 // We need sp to be 8 bytes aligned when calling the stub. | |
765 __ SetupAlignedCall(t0, arg_count); | |
766 | |
767 // Pass the global object as the receiver and let the IC stub | |
768 // patch the stack to use the global proxy as 'this' in the | |
769 // invoked function. | |
770 LoadGlobal(); | |
771 | |
772 // Load the arguments. | |
773 for (int i = 0; i < arg_count; i++) { | |
774 LoadAndSpill(args->at(i)); | |
775 } | |
776 | |
777 // Setup the receiver register and call the IC initialization code. | |
778 __ li(a2, Operand(var->name())); | |
779 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | |
780 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | |
781 CodeForSourcePosition(node->position()); | |
782 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | |
783 arg_count + 1); | |
784 __ ReturnFromAlignedCall(); | |
785 __ lw(cp, frame_->Context()); | |
786 // Remove the function from the stack. | |
787 frame_->EmitPush(v0); | |
788 | |
789 } else if (var != NULL && var->slot() != NULL && | |
790 var->slot()->type() == Slot::LOOKUP) { | |
791 UNIMPLEMENTED_MIPS(); | |
792 } else if (property != NULL) { | |
793 UNIMPLEMENTED_MIPS(); | |
794 } else { | |
795 UNIMPLEMENTED_MIPS(); | |
796 } | |
797 | |
798 ASSERT(frame_->height() == original_height + 1); | |
799 } | 626 } |
800 | 627 |
801 | 628 |
802 void CodeGenerator::VisitCallNew(CallNew* node) { | 629 void CodeGenerator::VisitCallNew(CallNew* node) { |
803 UNIMPLEMENTED_MIPS(); | 630 UNIMPLEMENTED_MIPS(); |
804 } | 631 } |
805 | 632 |
806 | 633 |
807 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 634 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
808 UNIMPLEMENTED_MIPS(); | 635 UNIMPLEMENTED_MIPS(); |
(...skipping 23 matching lines...) Expand all Loading... |
832 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 659 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
833 UNIMPLEMENTED_MIPS(); | 660 UNIMPLEMENTED_MIPS(); |
834 } | 661 } |
835 | 662 |
836 | 663 |
837 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { | 664 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { |
838 UNIMPLEMENTED_MIPS(); | 665 UNIMPLEMENTED_MIPS(); |
839 } | 666 } |
840 | 667 |
841 | 668 |
842 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | |
843 UNIMPLEMENTED_MIPS(); | |
844 } | |
845 | |
846 | |
847 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | |
848 UNIMPLEMENTED_MIPS(); | |
849 } | |
850 | |
851 | |
852 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { | 669 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
853 UNIMPLEMENTED_MIPS(); | 670 UNIMPLEMENTED_MIPS(); |
854 } | 671 } |
855 | 672 |
856 | 673 |
857 // This should generate code that performs a charCodeAt() call or returns | 674 class DeferredStringCharCodeAt : public DeferredCode { |
858 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | 675 public: |
859 // It is not yet implemented on ARM, so it always goes to the slow case. | 676 DeferredStringCharCodeAt(Register object, |
860 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 677 Register index, |
| 678 Register scratch, |
| 679 Register result) |
| 680 : result_(result), |
| 681 char_code_at_generator_(object, |
| 682 index, |
| 683 scratch, |
| 684 result, |
| 685 &need_conversion_, |
| 686 &need_conversion_, |
| 687 &index_out_of_range_, |
| 688 STRING_INDEX_IS_NUMBER) {} |
| 689 |
| 690 StringCharCodeAtGenerator* fast_case_generator() { |
| 691 return &char_code_at_generator_; |
| 692 } |
| 693 |
| 694 virtual void Generate() { |
| 695 UNIMPLEMENTED_MIPS(); |
| 696 } |
| 697 |
| 698 private: |
| 699 Register result_; |
| 700 |
| 701 Label need_conversion_; |
| 702 Label index_out_of_range_; |
| 703 |
| 704 StringCharCodeAtGenerator char_code_at_generator_; |
| 705 }; |
| 706 |
| 707 |
| 708 void CodeGenerator::GenerateStringCharCodeAt(ZoneList<Expression*>* args) { |
861 UNIMPLEMENTED_MIPS(); | 709 UNIMPLEMENTED_MIPS(); |
862 } | 710 } |
863 | 711 |
864 | 712 |
865 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { | 713 class DeferredStringCharFromCode : public DeferredCode { |
| 714 public: |
| 715 DeferredStringCharFromCode(Register code, |
| 716 Register result) |
| 717 : char_from_code_generator_(code, result) {} |
| 718 |
| 719 StringCharFromCodeGenerator* fast_case_generator() { |
| 720 return &char_from_code_generator_; |
| 721 } |
| 722 |
| 723 virtual void Generate() { |
| 724 VirtualFrameRuntimeCallHelper call_helper(frame_state()); |
| 725 char_from_code_generator_.GenerateSlow(masm(), call_helper); |
| 726 } |
| 727 |
| 728 private: |
| 729 StringCharFromCodeGenerator char_from_code_generator_; |
| 730 }; |
| 731 |
| 732 |
| 733 void CodeGenerator::GenerateStringCharFromCode(ZoneList<Expression*>* args) { |
866 UNIMPLEMENTED_MIPS(); | 734 UNIMPLEMENTED_MIPS(); |
867 } | 735 } |
868 | 736 |
| 737 |
| 738 class DeferredStringCharAt : public DeferredCode { |
| 739 public: |
| 740 DeferredStringCharAt(Register object, |
| 741 Register index, |
| 742 Register scratch1, |
| 743 Register scratch2, |
| 744 Register result) |
| 745 : result_(result), |
| 746 char_at_generator_(object, |
| 747 index, |
| 748 scratch1, |
| 749 scratch2, |
| 750 result, |
| 751 &need_conversion_, |
| 752 &need_conversion_, |
| 753 &index_out_of_range_, |
| 754 STRING_INDEX_IS_NUMBER) {} |
| 755 |
| 756 StringCharAtGenerator* fast_case_generator() { |
| 757 return &char_at_generator_; |
| 758 } |
| 759 |
| 760 virtual void Generate() { |
| 761 UNIMPLEMENTED_MIPS(); |
| 762 } |
| 763 |
| 764 private: |
| 765 Register result_; |
| 766 |
| 767 Label need_conversion_; |
| 768 Label index_out_of_range_; |
| 769 |
| 770 StringCharAtGenerator char_at_generator_; |
| 771 }; |
| 772 |
| 773 |
| 774 void CodeGenerator::GenerateStringCharAt(ZoneList<Expression*>* args) { |
| 775 UNIMPLEMENTED_MIPS(); |
| 776 } |
| 777 |
869 | 778 |
870 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | 779 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { |
871 UNIMPLEMENTED_MIPS(); | 780 UNIMPLEMENTED_MIPS(); |
872 } | 781 } |
873 | 782 |
874 | 783 |
875 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { | 784 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { |
876 UNIMPLEMENTED_MIPS(); | 785 UNIMPLEMENTED_MIPS(); |
877 } | 786 } |
878 | 787 |
879 | 788 |
| 789 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { |
| 790 UNIMPLEMENTED_MIPS(); |
| 791 } |
| 792 |
| 793 |
| 794 void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) { |
| 795 UNIMPLEMENTED_MIPS(); |
| 796 } |
| 797 |
| 798 |
| 799 class DeferredIsStringWrapperSafeForDefaultValueOf : public DeferredCode { |
| 800 public: |
| 801 DeferredIsStringWrapperSafeForDefaultValueOf(Register object, |
| 802 Register map_result, |
| 803 Register scratch1, |
| 804 Register scratch2) |
| 805 : object_(object), |
| 806 map_result_(map_result), |
| 807 scratch1_(scratch1), |
| 808 scratch2_(scratch2) { } |
| 809 |
| 810 virtual void Generate() { |
| 811 UNIMPLEMENTED_MIPS(); |
| 812 } |
| 813 |
| 814 private: |
| 815 Register object_; |
| 816 Register map_result_; |
| 817 Register scratch1_; |
| 818 Register scratch2_; |
| 819 }; |
| 820 |
| 821 |
| 822 void CodeGenerator::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 823 ZoneList<Expression*>* args) { |
| 824 UNIMPLEMENTED_MIPS(); |
| 825 } |
| 826 |
| 827 |
| 828 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
| 829 UNIMPLEMENTED_MIPS(); |
| 830 } |
| 831 |
| 832 |
| 833 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { |
| 834 UNIMPLEMENTED_MIPS(); |
| 835 } |
| 836 |
| 837 |
880 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { | 838 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { |
881 UNIMPLEMENTED_MIPS(); | 839 UNIMPLEMENTED_MIPS(); |
882 } | 840 } |
883 | 841 |
884 | 842 |
885 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 843 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
886 UNIMPLEMENTED_MIPS(); | 844 UNIMPLEMENTED_MIPS(); |
887 } | 845 } |
888 | 846 |
889 | 847 |
890 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { | 848 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { |
891 UNIMPLEMENTED_MIPS(); | 849 UNIMPLEMENTED_MIPS(); |
892 } | 850 } |
893 | 851 |
894 | 852 |
895 void CodeGenerator::GenerateRandomHeapNumber(ZoneList<Expression*>* args) { | 853 void CodeGenerator::GenerateRandomHeapNumber( |
| 854 ZoneList<Expression*>* args) { |
896 UNIMPLEMENTED_MIPS(); | 855 UNIMPLEMENTED_MIPS(); |
897 } | 856 } |
898 | 857 |
899 | |
900 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | |
901 UNIMPLEMENTED_MIPS(); | |
902 } | |
903 | |
904 | |
905 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { | |
906 UNIMPLEMENTED_MIPS(); | |
907 } | |
908 | |
909 | |
910 void CodeGenerator::GenerateIsSpecObject(ZoneList<Expression*>* args) { | |
911 UNIMPLEMENTED_MIPS(); | |
912 } | |
913 | |
914 | |
915 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { | |
916 UNIMPLEMENTED_MIPS(); | |
917 } | |
918 | |
919 | |
920 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { | |
921 UNIMPLEMENTED_MIPS(); | |
922 } | |
923 | |
924 | 858 |
925 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { | 859 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { |
926 UNIMPLEMENTED_MIPS(); | 860 UNIMPLEMENTED_MIPS(); |
927 } | 861 } |
928 | 862 |
929 | 863 |
930 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { | 864 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { |
931 UNIMPLEMENTED_MIPS(); | 865 UNIMPLEMENTED_MIPS(); |
932 } | 866 } |
933 | 867 |
934 | 868 |
935 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { | 869 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { |
936 UNIMPLEMENTED_MIPS(); | 870 UNIMPLEMENTED_MIPS(); |
937 } | 871 } |
938 | 872 |
939 | 873 |
940 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 874 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
941 UNIMPLEMENTED_MIPS(); | 875 UNIMPLEMENTED_MIPS(); |
942 } | 876 } |
943 | 877 |
944 | 878 |
| 879 void CodeGenerator::GenerateRegExpConstructResult(ZoneList<Expression*>* args) { |
| 880 UNIMPLEMENTED_MIPS(); |
| 881 } |
| 882 |
| 883 |
| 884 class DeferredSearchCache: public DeferredCode { |
| 885 public: |
| 886 DeferredSearchCache(Register dst, Register cache, Register key) |
| 887 : dst_(dst), cache_(cache), key_(key) { |
| 888 set_comment("[ DeferredSearchCache"); |
| 889 } |
| 890 |
| 891 virtual void Generate(); |
| 892 |
| 893 private: |
| 894 Register dst_, cache_, key_; |
| 895 }; |
| 896 |
| 897 |
| 898 void DeferredSearchCache::Generate() { |
| 899 UNIMPLEMENTED_MIPS(); |
| 900 } |
| 901 |
| 902 |
| 903 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { |
| 904 UNIMPLEMENTED_MIPS(); |
| 905 } |
| 906 |
| 907 |
945 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { | 908 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
946 UNIMPLEMENTED_MIPS(); | 909 UNIMPLEMENTED_MIPS(); |
947 } | 910 } |
948 | 911 |
949 | 912 |
| 913 class DeferredSwapElements: public DeferredCode { |
| 914 public: |
| 915 DeferredSwapElements(Register object, Register index1, Register index2) |
| 916 : object_(object), index1_(index1), index2_(index2) { |
| 917 set_comment("[ DeferredSwapElements"); |
| 918 } |
| 919 |
| 920 virtual void Generate(); |
| 921 |
| 922 private: |
| 923 Register object_, index1_, index2_; |
| 924 }; |
| 925 |
| 926 |
| 927 void DeferredSwapElements::Generate() { |
| 928 UNIMPLEMENTED_MIPS(); |
| 929 } |
| 930 |
| 931 |
| 932 void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) { |
| 933 UNIMPLEMENTED_MIPS(); |
| 934 } |
| 935 |
| 936 |
| 937 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { |
| 938 UNIMPLEMENTED_MIPS(); |
| 939 } |
| 940 |
| 941 |
| 942 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 943 UNIMPLEMENTED_MIPS(); |
| 944 } |
| 945 |
| 946 |
| 947 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| 948 UNIMPLEMENTED_MIPS(); |
| 949 } |
| 950 |
| 951 |
| 952 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { |
| 953 UNIMPLEMENTED_MIPS(); |
| 954 } |
| 955 |
| 956 |
| 957 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| 958 UNIMPLEMENTED_MIPS(); |
| 959 } |
| 960 |
| 961 |
| 962 void CodeGenerator::GenerateIsRegExpEquivalent(ZoneList<Expression*>* args) { |
| 963 UNIMPLEMENTED_MIPS(); |
| 964 } |
| 965 |
| 966 |
| 967 void CodeGenerator::GenerateHasCachedArrayIndex(ZoneList<Expression*>* args) { |
| 968 UNIMPLEMENTED_MIPS(); |
| 969 } |
| 970 |
| 971 |
| 972 void CodeGenerator::GenerateGetCachedArrayIndex(ZoneList<Expression*>* args) { |
| 973 UNIMPLEMENTED_MIPS(); |
| 974 } |
| 975 |
| 976 |
| 977 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) { |
| 978 UNIMPLEMENTED_MIPS(); |
| 979 } |
| 980 |
| 981 |
950 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 982 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
951 UNIMPLEMENTED_MIPS(); | 983 UNIMPLEMENTED_MIPS(); |
952 } | 984 } |
953 | 985 |
954 | 986 |
955 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 987 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
956 UNIMPLEMENTED_MIPS(); | 988 UNIMPLEMENTED_MIPS(); |
957 } | 989 } |
958 | 990 |
959 | 991 |
| 992 class DeferredCountOperation: public DeferredCode { |
| 993 public: |
| 994 DeferredCountOperation(Register value, |
| 995 bool is_increment, |
| 996 bool is_postfix, |
| 997 int target_size) |
| 998 : value_(value), |
| 999 is_increment_(is_increment), |
| 1000 is_postfix_(is_postfix), |
| 1001 target_size_(target_size) {} |
| 1002 |
| 1003 virtual void Generate() { |
| 1004 UNIMPLEMENTED_MIPS(); |
| 1005 } |
| 1006 |
| 1007 private: |
| 1008 Register value_; |
| 1009 bool is_increment_; |
| 1010 bool is_postfix_; |
| 1011 int target_size_; |
| 1012 }; |
| 1013 |
| 1014 |
960 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 1015 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
961 UNIMPLEMENTED_MIPS(); | 1016 UNIMPLEMENTED_MIPS(); |
962 } | 1017 } |
963 | 1018 |
964 | 1019 |
| 1020 void CodeGenerator::GenerateLogicalBooleanOperation(BinaryOperation* node) { |
| 1021 UNIMPLEMENTED_MIPS(); |
| 1022 } |
| 1023 |
| 1024 |
965 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 1025 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
966 UNIMPLEMENTED_MIPS(); | 1026 UNIMPLEMENTED_MIPS(); |
967 } | 1027 } |
968 | 1028 |
969 | 1029 |
970 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 1030 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
971 UNIMPLEMENTED_MIPS(); | 1031 UNIMPLEMENTED_MIPS(); |
972 } | 1032 } |
973 | 1033 |
974 | 1034 |
975 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 1035 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
976 UNIMPLEMENTED_MIPS(); | 1036 UNIMPLEMENTED_MIPS(); |
977 } | 1037 } |
978 | 1038 |
979 | 1039 |
| 1040 void CodeGenerator::VisitCompareToNull(CompareToNull* node) { |
| 1041 UNIMPLEMENTED_MIPS(); |
| 1042 } |
| 1043 |
| 1044 |
| 1045 class DeferredReferenceGetNamedValue: public DeferredCode { |
| 1046 public: |
| 1047 explicit DeferredReferenceGetNamedValue(Register receiver, |
| 1048 Handle<String> name, |
| 1049 bool is_contextual) |
| 1050 : receiver_(receiver), |
| 1051 name_(name), |
| 1052 is_contextual_(is_contextual), |
| 1053 is_dont_delete_(false) { |
| 1054 set_comment(is_contextual |
| 1055 ? "[ DeferredReferenceGetNamedValue (contextual)" |
| 1056 : "[ DeferredReferenceGetNamedValue"); |
| 1057 } |
| 1058 |
| 1059 virtual void Generate(); |
| 1060 |
| 1061 void set_is_dont_delete(bool value) { |
| 1062 ASSERT(is_contextual_); |
| 1063 is_dont_delete_ = value; |
| 1064 } |
| 1065 |
| 1066 private: |
| 1067 Register receiver_; |
| 1068 Handle<String> name_; |
| 1069 bool is_contextual_; |
| 1070 bool is_dont_delete_; |
| 1071 }; |
| 1072 |
| 1073 |
| 1074 |
| 1075 void DeferredReferenceGetNamedValue::Generate() { |
| 1076 UNIMPLEMENTED_MIPS(); |
| 1077 } |
| 1078 |
| 1079 |
| 1080 class DeferredReferenceGetKeyedValue: public DeferredCode { |
| 1081 public: |
| 1082 DeferredReferenceGetKeyedValue(Register key, Register receiver) |
| 1083 : key_(key), receiver_(receiver) { |
| 1084 set_comment("[ DeferredReferenceGetKeyedValue"); |
| 1085 } |
| 1086 |
| 1087 virtual void Generate(); |
| 1088 |
| 1089 private: |
| 1090 Register key_; |
| 1091 Register receiver_; |
| 1092 }; |
| 1093 |
| 1094 |
| 1095 void DeferredReferenceGetKeyedValue::Generate() { |
| 1096 UNIMPLEMENTED_MIPS(); |
| 1097 } |
| 1098 |
| 1099 |
| 1100 class DeferredReferenceSetKeyedValue: public DeferredCode { |
| 1101 public: |
| 1102 DeferredReferenceSetKeyedValue(Register value, |
| 1103 Register key, |
| 1104 Register receiver) |
| 1105 : value_(value), key_(key), receiver_(receiver) { |
| 1106 set_comment("[ DeferredReferenceSetKeyedValue"); |
| 1107 } |
| 1108 |
| 1109 virtual void Generate(); |
| 1110 |
| 1111 private: |
| 1112 Register value_; |
| 1113 Register key_; |
| 1114 Register receiver_; |
| 1115 }; |
| 1116 |
| 1117 |
| 1118 void DeferredReferenceSetKeyedValue::Generate() { |
| 1119 UNIMPLEMENTED_MIPS(); |
| 1120 } |
| 1121 |
| 1122 |
| 1123 class DeferredReferenceSetNamedValue: public DeferredCode { |
| 1124 public: |
| 1125 DeferredReferenceSetNamedValue(Register value, |
| 1126 Register receiver, |
| 1127 Handle<String> name) |
| 1128 : value_(value), receiver_(receiver), name_(name) { |
| 1129 set_comment("[ DeferredReferenceSetNamedValue"); |
| 1130 } |
| 1131 |
| 1132 virtual void Generate(); |
| 1133 |
| 1134 private: |
| 1135 Register value_; |
| 1136 Register receiver_; |
| 1137 Handle<String> name_; |
| 1138 }; |
| 1139 |
| 1140 |
| 1141 void DeferredReferenceSetNamedValue::Generate() { |
| 1142 UNIMPLEMENTED_MIPS(); |
| 1143 } |
| 1144 |
| 1145 |
| 1146 void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { |
| 1147 UNIMPLEMENTED_MIPS(); |
| 1148 } |
| 1149 |
| 1150 |
| 1151 void CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { |
| 1152 UNIMPLEMENTED_MIPS(); |
| 1153 } |
| 1154 |
| 1155 |
| 1156 void CodeGenerator::EmitKeyedLoad() { |
| 1157 UNIMPLEMENTED_MIPS(); |
| 1158 } |
| 1159 |
| 1160 |
| 1161 void CodeGenerator::EmitKeyedStore(StaticType* key_type, |
| 1162 WriteBarrierCharacter wb_info) { |
| 1163 UNIMPLEMENTED_MIPS(); |
| 1164 } |
| 1165 |
| 1166 |
980 #ifdef DEBUG | 1167 #ifdef DEBUG |
981 bool CodeGenerator::HasValidEntryRegisters() { return true; } | 1168 bool CodeGenerator::HasValidEntryRegisters() { |
| 1169 UNIMPLEMENTED_MIPS(); |
| 1170 return false; |
| 1171 } |
982 #endif | 1172 #endif |
983 | 1173 |
984 | 1174 |
985 #undef __ | 1175 #undef __ |
986 #define __ ACCESS_MASM(masm) | 1176 #define __ ACCESS_MASM(masm) |
987 | 1177 |
988 // ----------------------------------------------------------------------------- | 1178 // ----------------------------------------------------------------------------- |
989 // Reference support | 1179 // Reference support. |
990 | |
991 Reference::Reference(CodeGenerator* cgen, | |
992 Expression* expression, | |
993 bool persist_after_get) | |
994 : cgen_(cgen), | |
995 expression_(expression), | |
996 type_(ILLEGAL), | |
997 persist_after_get_(persist_after_get) { | |
998 cgen->LoadReference(this); | |
999 } | |
1000 | |
1001 | |
1002 Reference::~Reference() { | |
1003 ASSERT(is_unloaded() || is_illegal()); | |
1004 } | |
1005 | 1180 |
1006 | 1181 |
1007 Handle<String> Reference::GetName() { | 1182 Handle<String> Reference::GetName() { |
1008 ASSERT(type_ == NAMED); | 1183 UNIMPLEMENTED_MIPS(); |
1009 Property* property = expression_->AsProperty(); | 1184 return Handle<String>(); |
1010 if (property == NULL) { | 1185 } |
1011 // Global variable reference treated as a named property reference. | 1186 |
1012 VariableProxy* proxy = expression_->AsVariableProxy(); | 1187 |
1013 ASSERT(proxy->AsVariable() != NULL); | 1188 void Reference::DupIfPersist() { |
1014 ASSERT(proxy->AsVariable()->is_global()); | 1189 UNIMPLEMENTED_MIPS(); |
1015 return proxy->name(); | |
1016 } else { | |
1017 Literal* raw_name = property->key()->AsLiteral(); | |
1018 ASSERT(raw_name != NULL); | |
1019 return Handle<String>(String::cast(*raw_name->handle())); | |
1020 } | |
1021 } | 1190 } |
1022 | 1191 |
1023 | 1192 |
1024 void Reference::GetValue() { | 1193 void Reference::GetValue() { |
1025 ASSERT(cgen_->HasValidEntryRegisters()); | 1194 UNIMPLEMENTED_MIPS(); |
1026 ASSERT(!is_illegal()); | 1195 } |
1027 ASSERT(!cgen_->has_cc()); | 1196 |
1028 Property* property = expression_->AsProperty(); | 1197 |
1029 if (property != NULL) { | 1198 void Reference::SetValue(InitState init_state, WriteBarrierCharacter wb_info) { |
1030 cgen_->CodeForSourcePosition(property->position()); | 1199 UNIMPLEMENTED_MIPS(); |
1031 } | 1200 } |
1032 | 1201 |
1033 switch (type_) { | 1202 |
1034 case SLOT: { | 1203 const char* GenericBinaryOpStub::GetName() { |
1035 UNIMPLEMENTED_MIPS(); | 1204 UNIMPLEMENTED_MIPS(); |
1036 break; | 1205 return name_; |
1037 } | 1206 } |
1038 | 1207 |
1039 case NAMED: { | 1208 |
1040 UNIMPLEMENTED_MIPS(); | |
1041 break; | |
1042 } | |
1043 | |
1044 case KEYED: { | |
1045 UNIMPLEMENTED_MIPS(); | |
1046 break; | |
1047 } | |
1048 | |
1049 default: | |
1050 UNREACHABLE(); | |
1051 } | |
1052 } | |
1053 | |
1054 | |
1055 void Reference::SetValue(InitState init_state) { | |
1056 ASSERT(!is_illegal()); | |
1057 ASSERT(!cgen_->has_cc()); | |
1058 MacroAssembler* masm = cgen_->masm(); | |
1059 Property* property = expression_->AsProperty(); | |
1060 if (property != NULL) { | |
1061 cgen_->CodeForSourcePosition(property->position()); | |
1062 } | |
1063 | |
1064 switch (type_) { | |
1065 case SLOT: { | |
1066 Comment cmnt(masm, "[ Store to Slot"); | |
1067 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); | |
1068 cgen_->StoreToSlot(slot, init_state); | |
1069 cgen_->UnloadReference(this); | |
1070 break; | |
1071 } | |
1072 | |
1073 case NAMED: { | |
1074 UNIMPLEMENTED_MIPS(); | |
1075 break; | |
1076 } | |
1077 | |
1078 case KEYED: { | |
1079 UNIMPLEMENTED_MIPS(); | |
1080 break; | |
1081 } | |
1082 | |
1083 default: | |
1084 UNREACHABLE(); | |
1085 } | |
1086 } | |
1087 | |
1088 | |
1089 // On entry a0 and a1 are the things to be compared. On exit v0 is 0, | |
1090 // positive or negative to indicate the result of the comparison. | |
1091 void CompareStub::Generate(MacroAssembler* masm) { | |
1092 UNIMPLEMENTED_MIPS(); | |
1093 __ break_(0x765); | |
1094 } | |
1095 | |
1096 | |
1097 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { | |
1098 UNIMPLEMENTED_MIPS(); | |
1099 return Handle<Code>::null(); | |
1100 } | |
1101 | |
1102 | |
1103 void StackCheckStub::Generate(MacroAssembler* masm) { | |
1104 UNIMPLEMENTED_MIPS(); | |
1105 __ break_(0x790); | |
1106 } | |
1107 | |
1108 | |
1109 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | |
1110 UNIMPLEMENTED_MIPS(); | |
1111 __ break_(0x808); | |
1112 } | |
1113 | |
1114 | |
1115 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | |
1116 UncatchableExceptionType type) { | |
1117 UNIMPLEMENTED_MIPS(); | |
1118 __ break_(0x815); | |
1119 } | |
1120 | |
1121 void CEntryStub::GenerateCore(MacroAssembler* masm, | |
1122 Label* throw_normal_exception, | |
1123 Label* throw_termination_exception, | |
1124 Label* throw_out_of_memory_exception, | |
1125 bool do_gc, | |
1126 bool always_allocate) { | |
1127 // s0: number of arguments including receiver (C callee-saved) | |
1128 // s1: pointer to the first argument (C callee-saved) | |
1129 // s2: pointer to builtin function (C callee-saved) | |
1130 | |
1131 if (do_gc) { | |
1132 UNIMPLEMENTED_MIPS(); | |
1133 } | |
1134 | |
1135 ExternalReference scope_depth = | |
1136 ExternalReference::heap_always_allocate_scope_depth(); | |
1137 if (always_allocate) { | |
1138 UNIMPLEMENTED_MIPS(); | |
1139 } | |
1140 | |
1141 // Call C built-in. | |
1142 // a0 = argc, a1 = argv | |
1143 __ mov(a0, s0); | |
1144 __ mov(a1, s1); | |
1145 | |
1146 __ CallBuiltin(s2); | |
1147 | |
1148 if (always_allocate) { | |
1149 UNIMPLEMENTED_MIPS(); | |
1150 } | |
1151 | |
1152 // Check for failure result. | |
1153 Label failure_returned; | |
1154 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | |
1155 __ addiu(a2, v0, 1); | |
1156 __ andi(t0, a2, kFailureTagMask); | |
1157 __ Branch(eq, &failure_returned, t0, Operand(zero_reg)); | |
1158 | |
1159 // Exit C frame and return. | |
1160 // v0:v1: result | |
1161 // sp: stack pointer | |
1162 // fp: frame pointer | |
1163 __ LeaveExitFrame(mode_); | |
1164 | |
1165 // Check if we should retry or throw exception. | |
1166 Label retry; | |
1167 __ bind(&failure_returned); | |
1168 ASSERT(Failure::RETRY_AFTER_GC == 0); | |
1169 __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize); | |
1170 __ Branch(eq, &retry, t0, Operand(zero_reg)); | |
1171 | |
1172 // Special handling of out of memory exceptions. | |
1173 Failure* out_of_memory = Failure::OutOfMemoryException(); | |
1174 __ Branch(eq, throw_out_of_memory_exception, | |
1175 v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | |
1176 | |
1177 // Retrieve the pending exception and clear the variable. | |
1178 __ LoadExternalReference(t0, ExternalReference::the_hole_value_location()); | |
1179 __ lw(a3, MemOperand(t0)); | |
1180 __ LoadExternalReference(t0, | |
1181 ExternalReference(Isolate::k_pending_exception_address)); | |
1182 __ lw(v0, MemOperand(t0)); | |
1183 __ sw(a3, MemOperand(t0)); | |
1184 | |
1185 // Special handling of termination exceptions which are uncatchable | |
1186 // by javascript code. | |
1187 __ Branch(eq, throw_termination_exception, | |
1188 v0, Operand(FACTORY->termination_exception())); | |
1189 | |
1190 // Handle normal exception. | |
1191 __ b(throw_normal_exception); | |
1192 __ nop(); // Branch delay slot nop. | |
1193 | |
1194 __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying | |
1195 } | |
1196 | |
1197 void CEntryStub::Generate(MacroAssembler* masm) { | |
1198 // Called from JavaScript; parameters are on stack as if calling JS function | |
1199 // a0: number of arguments including receiver | |
1200 // a1: pointer to builtin function | |
1201 // fp: frame pointer (restored after C call) | |
1202 // sp: stack pointer (restored as callee's sp after C call) | |
1203 // cp: current context (C callee-saved) | |
1204 | |
1205 // NOTE: Invocations of builtins may return failure objects | |
1206 // instead of a proper result. The builtin entry handles | |
1207 // this by performing a garbage collection and retrying the | |
1208 // builtin once. | |
1209 | |
1210 // Enter the exit frame that transitions from JavaScript to C++. | |
1211 __ EnterExitFrame(mode_, s0, s1, s2); | |
1212 | |
1213 // s0: number of arguments (C callee-saved) | |
1214 // s1: pointer to first argument (C callee-saved) | |
1215 // s2: pointer to builtin function (C callee-saved) | |
1216 | |
1217 Label throw_normal_exception; | |
1218 Label throw_termination_exception; | |
1219 Label throw_out_of_memory_exception; | |
1220 | |
1221 // Call into the runtime system. | |
1222 GenerateCore(masm, | |
1223 &throw_normal_exception, | |
1224 &throw_termination_exception, | |
1225 &throw_out_of_memory_exception, | |
1226 false, | |
1227 false); | |
1228 | |
1229 // Do space-specific GC and retry runtime call. | |
1230 GenerateCore(masm, | |
1231 &throw_normal_exception, | |
1232 &throw_termination_exception, | |
1233 &throw_out_of_memory_exception, | |
1234 true, | |
1235 false); | |
1236 | |
1237 // Do full GC and retry runtime call one final time. | |
1238 Failure* failure = Failure::InternalError(); | |
1239 __ li(v0, Operand(reinterpret_cast<int32_t>(failure))); | |
1240 GenerateCore(masm, | |
1241 &throw_normal_exception, | |
1242 &throw_termination_exception, | |
1243 &throw_out_of_memory_exception, | |
1244 true, | |
1245 true); | |
1246 | |
1247 __ bind(&throw_out_of_memory_exception); | |
1248 GenerateThrowUncatchable(masm, OUT_OF_MEMORY); | |
1249 | |
1250 __ bind(&throw_termination_exception); | |
1251 GenerateThrowUncatchable(masm, TERMINATION); | |
1252 | |
1253 __ bind(&throw_normal_exception); | |
1254 GenerateThrowTOS(masm); | |
1255 } | |
1256 | |
1257 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | |
1258 Label invoke, exit; | |
1259 | |
1260 // Registers: | |
1261 // a0: entry address | |
1262 // a1: function | |
1263 // a2: reveiver | |
1264 // a3: argc | |
1265 // | |
1266 // Stack: | |
1267 // 4 args slots | |
1268 // args | |
1269 | |
1270 // Save callee saved registers on the stack. | |
1271 __ MultiPush((kCalleeSaved | ra.bit()) & ~sp.bit()); | |
1272 | |
1273 // We build an EntryFrame. | |
1274 __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. | |
1275 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | |
1276 __ li(t2, Operand(Smi::FromInt(marker))); | |
1277 __ li(t1, Operand(Smi::FromInt(marker))); | |
1278 __ LoadExternalReference(t0, | |
1279 ExternalReference(Isolate::k_c_entry_fp_address)); | |
1280 __ lw(t0, MemOperand(t0)); | |
1281 __ MultiPush(t0.bit() | t1.bit() | t2.bit() | t3.bit()); | |
1282 | |
1283 // Setup frame pointer for the frame to be pushed. | |
1284 __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); | |
1285 | |
1286 // Load argv in s0 register. | |
1287 __ lw(s0, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize + | |
1288 StandardFrameConstants::kCArgsSlotsSize)); | |
1289 | |
1290 // Registers: | |
1291 // a0: entry_address | |
1292 // a1: function | |
1293 // a2: reveiver_pointer | |
1294 // a3: argc | |
1295 // s0: argv | |
1296 // | |
1297 // Stack: | |
1298 // caller fp | | |
1299 // function slot | entry frame | |
1300 // context slot | | |
1301 // bad fp (0xff...f) | | |
1302 // callee saved registers + ra | |
1303 // 4 args slots | |
1304 // args | |
1305 | |
1306 // Call a faked try-block that does the invoke. | |
1307 __ bal(&invoke); | |
1308 __ nop(); // Branch delay slot nop. | |
1309 | |
1310 // Caught exception: Store result (exception) in the pending | |
1311 // exception field in the JSEnv and return a failure sentinel. | |
1312 // Coming in here the fp will be invalid because the PushTryHandler below | |
1313 // sets it to 0 to signal the existence of the JSEntry frame. | |
1314 __ LoadExternalReference(t0, | |
1315 ExternalReference(Isolate::k_pending_exception_address)); | |
1316 __ sw(v0, MemOperand(t0)); // We come back from 'invoke'. result is in v0. | |
1317 __ li(v0, Operand(reinterpret_cast<int32_t>(Failure::Exception()))); | |
1318 __ b(&exit); | |
1319 __ nop(); // Branch delay slot nop. | |
1320 | |
1321 // Invoke: Link this frame into the handler chain. | |
1322 __ bind(&invoke); | |
1323 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); | |
1324 // If an exception not caught by another handler occurs, this handler | |
1325 // returns control to the code after the bal(&invoke) above, which | |
1326 // restores all kCalleeSaved registers (including cp and fp) to their | |
1327 // saved values before returning a failure to C. | |
1328 | |
1329 // Clear any pending exceptions. | |
1330 __ LoadExternalReference(t0, ExternalReference::the_hole_value_location()); | |
1331 __ lw(t1, MemOperand(t0)); | |
1332 __ LoadExternalReference(t0, | |
1333 ExternalReference(Isolate::k_pending_exception_address)); | |
1334 __ sw(t1, MemOperand(t0)); | |
1335 | |
1336 // Invoke the function by calling through JS entry trampoline builtin. | |
1337 // Notice that we cannot store a reference to the trampoline code directly in | |
1338 // this stub, because runtime stubs are not traversed when doing GC. | |
1339 | |
1340 // Registers: | |
1341 // a0: entry_address | |
1342 // a1: function | |
1343 // a2: reveiver_pointer | |
1344 // a3: argc | |
1345 // s0: argv | |
1346 // | |
1347 // Stack: | |
1348 // handler frame | |
1349 // entry frame | |
1350 // callee saved registers + ra | |
1351 // 4 args slots | |
1352 // args | |
1353 | |
1354 if (is_construct) { | |
1355 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); | |
1356 __ LoadExternalReference(t0, construct_entry); | |
1357 } else { | |
1358 ExternalReference entry(Builtins::JSEntryTrampoline); | |
1359 __ LoadExternalReference(t0, entry); | |
1360 } | |
1361 __ lw(t9, MemOperand(t0)); // deref address | |
1362 | |
1363 // Call JSEntryTrampoline. | |
1364 __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); | |
1365 __ CallBuiltin(t9); | |
1366 | |
1367 // Unlink this frame from the handler chain. When reading the | |
1368 // address of the next handler, there is no need to use the address | |
1369 // displacement since the current stack pointer (sp) points directly | |
1370 // to the stack handler. | |
1371 __ lw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); | |
1372 __ LoadExternalReference(t0, ExternalReference(Isolate::k_handler_address)); | |
1373 __ sw(t1, MemOperand(t0)); | |
1374 | |
1375 // This restores sp to its position before PushTryHandler. | |
1376 __ addiu(sp, sp, StackHandlerConstants::kSize); | |
1377 | |
1378 __ bind(&exit); // v0 holds result | |
1379 // Restore the top frame descriptors from the stack. | |
1380 __ Pop(t1); | |
1381 __ LoadExternalReference(t0, | |
1382 ExternalReference(Isolate::k_c_entry_fp_address)); | |
1383 __ sw(t1, MemOperand(t0)); | |
1384 | |
1385 // Reset the stack to the callee saved registers. | |
1386 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); | |
1387 | |
1388 // Restore callee saved registers from the stack. | |
1389 __ MultiPop((kCalleeSaved | ra.bit()) & ~sp.bit()); | |
1390 // Return. | |
1391 __ Jump(ra); | |
1392 } | |
1393 | |
1394 | |
1395 // This stub performs an instanceof, calling the builtin function if | |
1396 // necessary. Uses a1 for the object, a0 for the function that it may | |
1397 // be an instance of (these are fetched from the stack). | |
1398 void InstanceofStub::Generate(MacroAssembler* masm) { | |
1399 UNIMPLEMENTED_MIPS(); | |
1400 __ break_(0x845); | |
1401 } | |
1402 | |
1403 | |
1404 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { | |
1405 UNIMPLEMENTED_MIPS(); | |
1406 __ break_(0x851); | |
1407 } | |
1408 | |
1409 | |
1410 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | |
1411 UNIMPLEMENTED_MIPS(); | |
1412 __ break_(0x857); | |
1413 } | |
1414 | |
1415 | |
1416 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { | |
1417 UNIMPLEMENTED_MIPS(); | |
1418 __ break_(0x863); | |
1419 } | |
1420 | |
1421 | |
1422 const char* CompareStub::GetName() { | |
1423 UNIMPLEMENTED_MIPS(); | |
1424 return NULL; // UNIMPLEMENTED RETURN | |
1425 } | |
1426 | |
1427 | |
1428 int CompareStub::MinorKey() { | |
1429 // Encode the two parameters in a unique 16 bit value. | |
1430 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); | |
1431 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); | |
1432 } | |
1433 | |
1434 | |
1435 #undef __ | 1209 #undef __ |
1436 | 1210 |
1437 } } // namespace v8::internal | 1211 } } // namespace v8::internal |
1438 | 1212 |
1439 #endif // V8_TARGET_ARCH_MIPS | 1213 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |