Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/mips/codegen-mips.cc

Issue 6759025: Version 3.2.6 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips/codegen-mips.h ('k') | src/mips/codegen-mips-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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_ = &register_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
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
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
OLDNEW
« no previous file with comments | « src/mips/codegen-mips.h ('k') | src/mips/codegen-mips-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698