Chromium Code Reviews| 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 } | 85 } |
| 86 | 86 |
| 87 | 87 |
| 88 CodeGenState::~CodeGenState() { | 88 CodeGenState::~CodeGenState() { |
| 89 ASSERT(owner_->state() == this); | 89 ASSERT(owner_->state() == this); |
| 90 owner_->set_state(previous_); | 90 owner_->set_state(previous_); |
| 91 } | 91 } |
| 92 | 92 |
| 93 | 93 |
| 94 // ----------------------------------------------------------------------------- | 94 // ----------------------------------------------------------------------------- |
| 95 // CodeGenerator implementation | 95 // CodeGenerator implementation. |
| 96 | 96 |
| 97 CodeGenerator::CodeGenerator(MacroAssembler* masm) | 97 CodeGenerator::CodeGenerator(MacroAssembler* masm) |
| 98 : deferred_(8), | 98 : deferred_(8), |
| 99 masm_(masm), | 99 masm_(masm), |
| 100 frame_(NULL), | 100 frame_(NULL), |
| 101 allocator_(NULL), | 101 allocator_(NULL), |
| 102 cc_reg_(cc_always), | 102 cc_reg_(cc_always), |
| 103 state_(NULL), | 103 state_(NULL), |
| 104 function_return_is_shadowed_(false) { | 104 function_return_is_shadowed_(false) { |
| 105 } | 105 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 // Allocate space for locals and initialize them. | 143 // Allocate space for locals and initialize them. |
| 144 frame_->AllocateStackSlots(); | 144 frame_->AllocateStackSlots(); |
| 145 | 145 |
| 146 // Initialize the function return target. | 146 // Initialize the function return target. |
| 147 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); | 147 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); |
| 148 function_return_is_shadowed_ = false; | 148 function_return_is_shadowed_ = false; |
| 149 | 149 |
| 150 VirtualFrame::SpilledScope spilled_scope; | 150 VirtualFrame::SpilledScope spilled_scope; |
| 151 if (scope()->num_heap_slots() > 0) { | 151 if (scope()->num_heap_slots() > 0) { |
| 152 UNIMPLEMENTED_MIPS(); | 152 UNIMPLEMENTED_MIPS(); |
| 153 __ break_(__LINE__); | |
| 153 } | 154 } |
| 154 | 155 |
| 155 { | 156 { |
| 156 Comment cmnt2(masm_, "[ copy context parameters into .context"); | 157 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
| 157 | 158 |
| 158 // Note that iteration order is relevant here! If we have the same | 159 // Note that iteration order is relevant here! If we have the same |
| 159 // parameter twice (e.g., function (x, y, x)), and that parameter | 160 // parameter twice (e.g., function (x, y, x)), and that parameter |
| 160 // needs to be copied into the context, it must be the last argument | 161 // needs to be copied into the context, it must be the last argument |
| 161 // passed to the parameter that needs to be copied. This is a rare | 162 // passed to the parameter that needs to be copied. This is a rare |
| 162 // case so we don't check for it, instead we rely on the copying | 163 // case so we don't check for it, instead we rely on the copying |
| 163 // order: such a parameter is copied repeatedly into the same | 164 // order: such a parameter is copied repeatedly into the same |
| 164 // context location and thus the last value is what is seen inside | 165 // context location and thus the last value is what is seen inside |
| 165 // the function. | 166 // the function. |
| 166 for (int i = 0; i < scope()->num_parameters(); i++) { | 167 for (int i = 0; i < scope()->num_parameters(); i++) { |
| 167 UNIMPLEMENTED_MIPS(); | 168 UNIMPLEMENTED_MIPS(); |
| 168 } | 169 } |
| 169 } | 170 } |
| 170 | 171 |
| 171 // Store the arguments object. This must happen after context | 172 // Store the arguments object. This must happen after context |
| 172 // initialization because the arguments object may be stored in the | 173 // initialization because the arguments object may be stored in the |
| 173 // context. | 174 // context. |
| 174 if (scope()->arguments() != NULL) { | 175 if (scope()->arguments() != NULL) { |
| 175 UNIMPLEMENTED_MIPS(); | 176 UNIMPLEMENTED_MIPS(); |
| 177 __ break_(__LINE__); | |
| 176 } | 178 } |
| 177 | 179 |
| 178 // Generate code to 'execute' declarations and initialize functions | 180 // Generate code to 'execute' declarations and initialize functions |
| 179 // (source elements). In case of an illegal redeclaration we need to | 181 // (source elements). In case of an illegal redeclaration we need to |
| 180 // handle that instead of processing the declarations. | 182 // handle that instead of processing the declarations. |
| 181 if (scope()->HasIllegalRedeclaration()) { | 183 if (scope()->HasIllegalRedeclaration()) { |
| 182 Comment cmnt(masm_, "[ illegal redeclarations"); | 184 Comment cmnt(masm_, "[ illegal redeclarations"); |
| 183 scope()->VisitIllegalRedeclaration(this); | 185 scope()->VisitIllegalRedeclaration(this); |
| 184 } else { | 186 } else { |
| 185 Comment cmnt(masm_, "[ declarations"); | 187 Comment cmnt(masm_, "[ declarations"); |
| 186 ProcessDeclarations(scope()->declarations()); | 188 ProcessDeclarations(scope()->declarations()); |
| 187 // Bail out if a stack-overflow exception occurred when processing | 189 // Bail out if a stack-overflow exception occurred when processing |
| 188 // declarations. | 190 // declarations. |
| 189 if (HasStackOverflow()) return; | 191 if (HasStackOverflow()) return; |
| 190 } | 192 } |
| 191 | 193 |
| 192 if (FLAG_trace) { | 194 if (FLAG_trace) { |
| 193 UNIMPLEMENTED_MIPS(); | 195 UNIMPLEMENTED_MIPS(); |
| 196 __ break_(__LINE__); | |
| 194 } | 197 } |
| 195 | 198 |
| 196 // Compile the body of the function in a vanilla state. Don't | 199 // Compile the body of the function in a vanilla state. Don't |
| 197 // bother compiling all the code if the scope has an illegal | 200 // bother compiling all the code if the scope has an illegal |
| 198 // redeclaration. | 201 // redeclaration. |
| 199 if (!scope()->HasIllegalRedeclaration()) { | 202 if (!scope()->HasIllegalRedeclaration()) { |
| 200 Comment cmnt(masm_, "[ function body"); | 203 Comment cmnt(masm_, "[ function body"); |
| 201 #ifdef DEBUG | 204 #ifdef DEBUG |
| 202 bool is_builtin = Bootstrapper::IsActive(); | 205 bool is_builtin = Bootstrapper::IsActive(); |
| 203 bool should_trace = | 206 bool should_trace = |
| 204 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 207 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
| 205 if (should_trace) { | 208 if (should_trace) { |
| 206 UNIMPLEMENTED_MIPS(); | 209 UNIMPLEMENTED_MIPS(); |
| 210 __ break_(__LINE__); | |
| 207 } | 211 } |
| 208 #endif | 212 #endif |
| 209 VisitStatementsAndSpill(info->function()->body()); | 213 VisitStatementsAndSpill(info->function()->body()); |
| 210 } | 214 } |
| 211 } | 215 } |
| 212 | 216 |
| 213 if (has_valid_frame() || function_return_.is_linked()) { | 217 if (has_valid_frame() || function_return_.is_linked()) { |
| 214 if (!function_return_.is_linked()) { | 218 if (!function_return_.is_linked()) { |
| 215 CodeForReturnPosition(info->function()); | 219 CodeForReturnPosition(info->function()); |
| 216 } | 220 } |
| 217 // Registers: | 221 // Registers: |
| 218 // v0: result | 222 // v0: result |
| 219 // sp: stack pointer | 223 // sp: stack pointer |
| 220 // fp: frame pointer | 224 // fp: frame pointer |
| 221 // cp: callee's context | 225 // cp: callee's context |
| 222 | 226 |
| 223 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 227 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 224 | 228 |
| 225 function_return_.Bind(); | 229 function_return_.Bind(); |
| 226 if (FLAG_trace) { | 230 if (FLAG_trace) { |
| 227 UNIMPLEMENTED_MIPS(); | 231 UNIMPLEMENTED_MIPS(); |
| 232 __ break_(__LINE__); | |
| 228 } | 233 } |
| 229 | 234 |
| 230 // Add a label for checking the size of the code used for returning. | 235 // We don't check for the return code size. It may differ if the number of |
| 231 Label check_exit_codesize; | 236 // arguments is too big. |
| 232 masm_->bind(&check_exit_codesize); | 237 __ mov(sp, fp); |
| 238 __ lw(fp, MemOperand(sp, 0)); | |
| 239 __ lw(ra, MemOperand(sp, 4)); | |
| 240 __ addiu(sp, sp, 8); | |
| 233 | 241 |
| 234 masm_->mov(sp, fp); | 242 __ Addu(sp, sp, Operand((scope()->num_parameters() + 1) * kPointerSize)); |
| 235 masm_->lw(fp, MemOperand(sp, 0)); | 243 __ Ret(); |
| 236 masm_->lw(ra, MemOperand(sp, 4)); | |
| 237 masm_->addiu(sp, sp, 8); | |
| 238 | |
| 239 // Here we use masm_-> instead of the __ macro to avoid the code coverage | |
| 240 // tool from instrumenting as we rely on the code size here. | |
| 241 // TODO(MIPS): Should we be able to use more than 0x1ffe parameters? | |
| 242 masm_->addiu(sp, sp, (scope()->num_parameters() + 1) * kPointerSize); | |
| 243 masm_->Jump(ra); | |
| 244 // The Jump automatically generates a nop in the branch delay slot. | |
| 245 | |
| 246 // Check that the size of the code used for returning matches what is | |
| 247 // expected by the debugger. | |
| 248 ASSERT_EQ(kJSReturnSequenceLength, | |
| 249 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | |
| 250 } | 244 } |
| 251 | 245 |
| 252 // Code generation state must be reset. | 246 // Code generation state must be reset. |
| 253 ASSERT(!has_cc()); | 247 ASSERT(!has_cc()); |
| 254 ASSERT(state_ == NULL); | 248 ASSERT(state_ == NULL); |
| 255 ASSERT(!function_return_is_shadowed_); | 249 ASSERT(!function_return_is_shadowed_); |
| 256 function_return_.Unuse(); | 250 function_return_.Unuse(); |
| 257 DeleteFrame(); | 251 DeleteFrame(); |
| 258 | 252 |
| 259 // Process any deferred code using the register allocator. | 253 // Process any deferred code using the register allocator. |
| 260 if (!HasStackOverflow()) { | 254 if (!HasStackOverflow()) { |
| 261 ProcessDeferred(); | 255 ProcessDeferred(); |
| 262 } | 256 } |
| 263 | 257 |
| 264 allocator_ = NULL; | 258 allocator_ = NULL; |
| 265 } | 259 } |
| 266 | 260 |
| 267 | 261 |
| 268 void CodeGenerator::LoadReference(Reference* ref) { | 262 void CodeGenerator::LoadReference(Reference* ref) { |
| 269 VirtualFrame::SpilledScope spilled_scope; | 263 VirtualFrame::SpilledScope spilled_scope; |
| 270 Comment cmnt(masm_, "[ LoadReference"); | 264 Comment cmnt(masm_, "[ LoadReference"); |
| 271 Expression* e = ref->expression(); | 265 Expression* e = ref->expression(); |
| 272 Property* property = e->AsProperty(); | 266 Property* property = e->AsProperty(); |
| 273 Variable* var = e->AsVariableProxy()->AsVariable(); | 267 Variable* var = e->AsVariableProxy()->AsVariable(); |
| 274 | 268 |
| 275 if (property != NULL) { | 269 if (property != NULL) { |
| 276 UNIMPLEMENTED_MIPS(); | 270 UNIMPLEMENTED_MIPS(); |
| 277 } else if (var != NULL) { | 271 } else if (var != NULL) { |
| 278 // The expression is a variable proxy that does not rewrite to a | 272 // The expression is a variable proxy that does not rewrite to a |
| 279 // property. Global variables are treated as named property references. | 273 // property. Global variables are treated as named property references. |
| 280 if (var->is_global()) { | 274 if (var->is_global()) { |
| 281 LoadGlobal(); | 275 LoadGlobal(); |
| 282 ref->set_type(Reference::NAMED); | 276 ref->set_type(Reference::NAMED); |
| 283 } else { | 277 } else { |
| 284 ASSERT(var->slot() != NULL); | 278 ASSERT(var->slot() != NULL); |
| 285 ref->set_type(Reference::SLOT); | 279 ref->set_type(Reference::SLOT); |
| 286 } | 280 } |
| 287 } else { | 281 } else { |
| 288 UNIMPLEMENTED_MIPS(); | 282 UNIMPLEMENTED_MIPS(); |
| 283 __ break_(__LINE__); | |
| 289 } | 284 } |
| 290 } | 285 } |
| 291 | 286 |
| 292 | 287 |
| 293 void CodeGenerator::UnloadReference(Reference* ref) { | 288 void CodeGenerator::UnloadReference(Reference* ref) { |
| 294 VirtualFrame::SpilledScope spilled_scope; | 289 VirtualFrame::SpilledScope spilled_scope; |
| 295 // Pop a reference from the stack while preserving TOS. | 290 // Pop a reference from the stack while preserving TOS. |
| 296 Comment cmnt(masm_, "[ UnloadReference"); | 291 Comment cmnt(masm_, "[ UnloadReference"); |
| 297 int size = ref->size(); | 292 int size = ref->size(); |
| 298 if (size > 0) { | 293 if (size > 0) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 310 // (such as the variable referring to a named function expression). | 305 // (such as the variable referring to a named function expression). |
| 311 // We need to implement assignments to read-only variables. | 306 // We need to implement assignments to read-only variables. |
| 312 // Ideally, we should do this during AST generation (by converting | 307 // Ideally, we should do this during AST generation (by converting |
| 313 // such assignments into expression statements); however, in general | 308 // such assignments into expression statements); however, in general |
| 314 // we may not be able to make the decision until past AST generation, | 309 // we may not be able to make the decision until past AST generation, |
| 315 // that is when the entire program is known. | 310 // that is when the entire program is known. |
| 316 ASSERT(slot != NULL); | 311 ASSERT(slot != NULL); |
| 317 int index = slot->index(); | 312 int index = slot->index(); |
| 318 switch (slot->type()) { | 313 switch (slot->type()) { |
| 319 case Slot::PARAMETER: | 314 case Slot::PARAMETER: |
| 320 UNIMPLEMENTED_MIPS(); | 315 return frame_->ParameterAt(index); |
| 321 return MemOperand(no_reg, 0); | |
| 322 | |
| 323 case Slot::LOCAL: | 316 case Slot::LOCAL: |
| 324 return frame_->LocalAt(index); | 317 return frame_->LocalAt(index); |
| 325 | 318 |
| 326 case Slot::CONTEXT: { | 319 case Slot::CONTEXT: { |
| 327 UNIMPLEMENTED_MIPS(); | 320 UNIMPLEMENTED_MIPS(); |
| 328 return MemOperand(no_reg, 0); | 321 return MemOperand(no_reg, 0); |
| 329 } | 322 } |
| 330 | 323 |
| 331 default: | 324 default: |
| 332 UNREACHABLE(); | 325 UNREACHABLE(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 void CodeGenerator::Load(Expression* x) { | 374 void CodeGenerator::Load(Expression* x) { |
| 382 #ifdef DEBUG | 375 #ifdef DEBUG |
| 383 int original_height = frame_->height(); | 376 int original_height = frame_->height(); |
| 384 #endif | 377 #endif |
| 385 JumpTarget true_target; | 378 JumpTarget true_target; |
| 386 JumpTarget false_target; | 379 JumpTarget false_target; |
| 387 LoadCondition(x, &true_target, &false_target, false); | 380 LoadCondition(x, &true_target, &false_target, false); |
| 388 | 381 |
| 389 if (has_cc()) { | 382 if (has_cc()) { |
| 390 UNIMPLEMENTED_MIPS(); | 383 UNIMPLEMENTED_MIPS(); |
| 384 __ break_(__LINE__); | |
| 391 } | 385 } |
| 392 | 386 |
| 393 if (true_target.is_linked() || false_target.is_linked()) { | 387 if (true_target.is_linked() || false_target.is_linked()) { |
| 394 UNIMPLEMENTED_MIPS(); | 388 UNIMPLEMENTED_MIPS(); |
| 389 __ break_(__LINE__); | |
| 395 } | 390 } |
| 396 ASSERT(has_valid_frame()); | 391 ASSERT(has_valid_frame()); |
| 397 ASSERT(!has_cc()); | 392 ASSERT(!has_cc()); |
| 398 ASSERT(frame_->height() == original_height + 1); | 393 ASSERT(frame_->height() == original_height + 1); |
| 399 } | 394 } |
| 400 | 395 |
| 401 | 396 |
| 402 void CodeGenerator::LoadGlobal() { | 397 void CodeGenerator::LoadGlobal() { |
| 403 VirtualFrame::SpilledScope spilled_scope; | 398 VirtualFrame::SpilledScope spilled_scope; |
| 404 __ lw(a0, GlobalObject()); | 399 __ lw(a0, GlobalObject()); |
| 405 frame_->EmitPush(a0); | 400 frame_->EmitPush(a0); |
| 406 } | 401 } |
| 407 | 402 |
| 408 | 403 |
| 409 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { | 404 void CodeGenerator::LoadFromSlot(Slot* slot, TypeofState typeof_state) { |
| 410 VirtualFrame::SpilledScope spilled_scope; | 405 VirtualFrame::SpilledScope spilled_scope; |
| 411 if (slot->type() == Slot::LOOKUP) { | 406 if (slot->type() == Slot::LOOKUP) { |
| 412 UNIMPLEMENTED_MIPS(); | 407 UNIMPLEMENTED_MIPS(); |
| 408 __ break_(__LINE__); | |
| 413 } else { | 409 } else { |
| 414 __ lw(a0, SlotOperand(slot, a2)); | 410 __ lw(v0, SlotOperand(slot, a2)); |
| 415 frame_->EmitPush(a0); | 411 frame_->EmitPush(v0); |
| 416 if (slot->var()->mode() == Variable::CONST) { | 412 if (slot->var()->mode() == Variable::CONST) { |
| 417 UNIMPLEMENTED_MIPS(); | 413 UNIMPLEMENTED_MIPS(); |
| 414 __ break_(__LINE__); | |
| 418 } | 415 } |
| 419 } | 416 } |
| 420 } | 417 } |
| 421 | 418 |
| 422 | 419 |
| 423 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { | 420 void CodeGenerator::StoreToSlot(Slot* slot, InitState init_state) { |
| 424 ASSERT(slot != NULL); | 421 ASSERT(slot != NULL); |
| 425 if (slot->type() == Slot::LOOKUP) { | 422 if (slot->type() == Slot::LOOKUP) { |
| 426 UNIMPLEMENTED_MIPS(); | 423 UNIMPLEMENTED_MIPS(); |
| 424 __ break_(__LINE__); | |
| 427 } else { | 425 } else { |
| 428 ASSERT(!slot->var()->is_dynamic()); | 426 ASSERT(!slot->var()->is_dynamic()); |
| 429 | 427 |
| 430 JumpTarget exit; | 428 JumpTarget exit; |
| 431 if (init_state == CONST_INIT) { | 429 if (init_state == CONST_INIT) { |
| 432 UNIMPLEMENTED_MIPS(); | 430 UNIMPLEMENTED_MIPS(); |
| 431 __ break_(__LINE__); | |
| 433 } | 432 } |
| 434 | 433 |
| 435 // We must execute the store. Storing a variable must keep the | 434 // We must execute the store. Storing a variable must keep the |
| 436 // (new) value on the stack. This is necessary for compiling | 435 // (new) value on the stack. This is necessary for compiling |
| 437 // assignment expressions. | 436 // assignment expressions. |
| 438 // | 437 // |
| 439 // Note: We will reach here even with slot->var()->mode() == | 438 // Note: We will reach here even with slot->var()->mode() == |
| 440 // Variable::CONST because of const declarations which will | 439 // Variable::CONST because of const declarations which will |
| 441 // initialize consts to 'the hole' value and by doing so, end up | 440 // initialize consts to 'the hole' value and by doing so, end up |
| 442 // calling this code. a2 may be loaded with context; used below in | 441 // calling this code. a2 may be loaded with context; used below in |
| 443 // RecordWrite. | 442 // RecordWrite. |
| 444 frame_->EmitPop(a0); | 443 frame_->EmitPop(a0); |
| 445 __ sw(a0, SlotOperand(slot, a2)); | 444 __ sw(a0, SlotOperand(slot, a2)); |
| 446 frame_->EmitPush(a0); | 445 frame_->EmitPush(a0); |
| 447 if (slot->type() == Slot::CONTEXT) { | 446 if (slot->type() == Slot::CONTEXT) { |
| 448 UNIMPLEMENTED_MIPS(); | 447 UNIMPLEMENTED_MIPS(); |
| 448 __ break_(__LINE__); | |
| 449 } | 449 } |
| 450 // If we definitely did not jump over the assignment, we do not need | 450 // If we definitely did not jump over the assignment, we do not need |
| 451 // to bind the exit label. Doing so can defeat peephole | 451 // to bind the exit label. Doing so can defeat peephole |
| 452 // optimization. | 452 // optimization. |
| 453 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { | 453 if (init_state == CONST_INIT || slot->type() == Slot::CONTEXT) { |
| 454 exit.Bind(); | 454 exit.Bind(); |
| 455 } | 455 } |
| 456 } | 456 } |
| 457 } | 457 } |
| 458 | 458 |
| 459 | 459 |
| 460 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 460 void CodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 461 VirtualFrame::SpilledScope spilled_scope; | 461 VirtualFrame::SpilledScope spilled_scope; |
| 462 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { | 462 for (int i = 0; frame_ != NULL && i < statements->length(); i++) { |
| 463 VisitAndSpill(statements->at(i)); | 463 VisitAndSpill(statements->at(i)); |
| 464 } | 464 } |
| 465 } | 465 } |
| 466 | 466 |
| 467 | 467 |
| 468 void CodeGenerator::VisitBlock(Block* node) { | 468 void CodeGenerator::VisitBlock(Block* node) { |
| 469 UNIMPLEMENTED_MIPS(); | 469 #ifdef DEBUG |
| 470 int original_height = frame_->height(); | |
| 471 #endif | |
| 472 VirtualFrame::SpilledScope spilled_scope; | |
| 473 Comment cmnt(masm_, "[ Block"); | |
| 474 CodeForStatementPosition(node); | |
| 475 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | |
| 476 VisitStatementsAndSpill(node->statements()); | |
| 477 if (node->break_target()->is_linked()) { | |
| 478 node->break_target()->Bind(); | |
| 479 } | |
| 480 node->break_target()->Unuse(); | |
| 481 ASSERT(!has_valid_frame() || frame_->height() == original_height); | |
| 470 } | 482 } |
| 471 | 483 |
| 472 | 484 |
| 473 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 485 void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
| 474 VirtualFrame::SpilledScope spilled_scope; | 486 VirtualFrame::SpilledScope spilled_scope; |
| 475 frame_->EmitPush(cp); | 487 frame_->EmitPush(cp); |
| 476 __ li(t0, Operand(pairs)); | 488 __ li(t0, Operand(pairs)); |
| 477 frame_->EmitPush(t0); | 489 frame_->EmitPush(t0); |
| 478 __ li(t0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); | 490 __ li(t0, Operand(Smi::FromInt(is_eval() ? 1 : 0))); |
| 479 frame_->EmitPush(t0); | 491 frame_->EmitPush(t0); |
| 480 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); | 492 frame_->CallRuntime(Runtime::kDeclareGlobals, 3); |
| 481 // The result is discarded. | 493 // The result is discarded. |
| 482 } | 494 } |
| 483 | 495 |
| 484 | 496 |
| 485 void CodeGenerator::VisitDeclaration(Declaration* node) { | 497 void CodeGenerator::VisitDeclaration(Declaration* node) { |
| 486 UNIMPLEMENTED_MIPS(); | 498 #ifdef DEBUG |
| 499 int original_height = frame_->height(); | |
| 500 #endif | |
| 501 VirtualFrame::SpilledScope spilled_scope; | |
| 502 Comment cmnt(masm_, "[ Declaration"); | |
| 503 Variable* var = node->proxy()->var(); | |
| 504 ASSERT(var != NULL); // Must have been resolved. | |
| 505 Slot* slot = var->slot(); | |
| 506 | |
| 507 // If it was not possible to allocate the variable at compile time, | |
| 508 // we need to "declare" it at runtime to make sure it actually | |
| 509 // exists in the local context. | |
| 510 if (slot != NULL && slot->type() == Slot::LOOKUP) { | |
| 511 UNIMPLEMENTED_MIPS(); | |
| 512 __ break_(__LINE__); | |
| 513 return; | |
| 514 } | |
| 515 | |
| 516 ASSERT(!var->is_global()); | |
| 517 | |
| 518 // If we have a function or a constant, we need to initialize the variable. | |
| 519 Expression* val = NULL; | |
| 520 if (node->mode() == Variable::CONST) { | |
| 521 UNIMPLEMENTED_MIPS(); | |
| 522 __ break_(__LINE__); | |
| 523 } else { | |
| 524 val = node->fun(); // NULL if we don't have a function. | |
| 525 } | |
| 526 | |
| 527 if (val != NULL) { | |
| 528 { | |
| 529 // Set initial value. | |
| 530 Reference target(this, node->proxy()); | |
| 531 LoadAndSpill(val); | |
| 532 target.SetValue(NOT_CONST_INIT); | |
| 533 // The reference is removed from the stack (preserving TOS) when | |
| 534 // it goes out of scope. | |
| 535 } | |
| 536 // Get rid of the assigned value (declarations are statements). | |
| 537 frame_->Drop(); | |
| 538 } | |
| 539 ASSERT(frame_->height() == original_height); | |
| 487 } | 540 } |
| 488 | 541 |
| 489 | 542 |
| 490 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { | 543 void CodeGenerator::VisitExpressionStatement(ExpressionStatement* node) { |
| 491 #ifdef DEBUG | 544 #ifdef DEBUG |
| 492 int original_height = frame_->height(); | 545 int original_height = frame_->height(); |
| 493 #endif | 546 #endif |
| 494 VirtualFrame::SpilledScope spilled_scope; | 547 VirtualFrame::SpilledScope spilled_scope; |
| 495 Comment cmnt(masm_, "[ ExpressionStatement"); | 548 Comment cmnt(masm_, "[ ExpressionStatement"); |
| 496 CodeForStatementPosition(node); | 549 CodeForStatementPosition(node); |
| 497 Expression* expression = node->expression(); | 550 Expression* expression = node->expression(); |
| 498 expression->MarkAsStatement(); | 551 expression->MarkAsStatement(); |
| 499 LoadAndSpill(expression); | 552 LoadAndSpill(expression); |
| 500 frame_->Drop(); | 553 frame_->Drop(); |
| 501 ASSERT(frame_->height() == original_height); | 554 ASSERT(frame_->height() == original_height); |
| 502 } | 555 } |
| 503 | 556 |
| 504 | 557 |
| 505 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { | 558 void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
| 506 UNIMPLEMENTED_MIPS(); | 559 UNIMPLEMENTED_MIPS(); |
| 560 __ break_(__LINE__); | |
| 507 } | 561 } |
| 508 | 562 |
| 509 | 563 |
| 510 void CodeGenerator::VisitIfStatement(IfStatement* node) { | 564 void CodeGenerator::VisitIfStatement(IfStatement* node) { |
| 511 UNIMPLEMENTED_MIPS(); | 565 UNIMPLEMENTED_MIPS(); |
| 566 __ break_(__LINE__); | |
| 512 } | 567 } |
| 513 | 568 |
| 514 | 569 |
| 515 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { | 570 void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
| 516 UNIMPLEMENTED_MIPS(); | 571 UNIMPLEMENTED_MIPS(); |
| 572 __ break_(__LINE__); | |
| 517 } | 573 } |
| 518 | 574 |
| 519 | 575 |
| 520 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { | 576 void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
| 521 UNIMPLEMENTED_MIPS(); | 577 UNIMPLEMENTED_MIPS(); |
| 578 __ break_(__LINE__); | |
| 522 } | 579 } |
| 523 | 580 |
| 524 | 581 |
| 525 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { | 582 void CodeGenerator::VisitReturnStatement(ReturnStatement* node) { |
| 526 VirtualFrame::SpilledScope spilled_scope; | 583 VirtualFrame::SpilledScope spilled_scope; |
| 527 Comment cmnt(masm_, "[ ReturnStatement"); | 584 Comment cmnt(masm_, "[ ReturnStatement"); |
| 528 | 585 |
| 529 CodeForStatementPosition(node); | 586 CodeForStatementPosition(node); |
| 530 LoadAndSpill(node->expression()); | 587 LoadAndSpill(node->expression()); |
| 531 if (function_return_is_shadowed_) { | 588 if (function_return_is_shadowed_) { |
| 532 frame_->EmitPop(v0); | 589 frame_->EmitPop(v0); |
| 533 function_return_.Jump(); | 590 function_return_.Jump(); |
| 534 } else { | 591 } else { |
| 535 // Pop the result from the frame and prepare the frame for | 592 // Pop the result from the frame and prepare the frame for |
| 536 // returning thus making it easier to merge. | 593 // returning thus making it easier to merge. |
| 537 frame_->EmitPop(v0); | 594 frame_->EmitPop(v0); |
| 538 frame_->PrepareForReturn(); | 595 frame_->PrepareForReturn(); |
| 539 | 596 |
| 540 function_return_.Jump(); | 597 function_return_.Jump(); |
| 541 } | 598 } |
| 542 } | 599 } |
| 543 | 600 |
| 544 | 601 |
| 545 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { | 602 void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
| 546 UNIMPLEMENTED_MIPS(); | 603 UNIMPLEMENTED_MIPS(); |
| 604 __ break_(__LINE__); | |
| 547 } | 605 } |
| 548 | 606 |
| 549 | 607 |
| 550 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 608 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
| 551 UNIMPLEMENTED_MIPS(); | 609 UNIMPLEMENTED_MIPS(); |
| 610 __ break_(__LINE__); | |
| 552 } | 611 } |
| 553 | 612 |
| 554 | 613 |
| 555 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { | 614 void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
| 556 UNIMPLEMENTED_MIPS(); | 615 UNIMPLEMENTED_MIPS(); |
| 616 __ break_(__LINE__); | |
| 557 } | 617 } |
| 558 | 618 |
| 559 | 619 |
| 560 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { | 620 void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { |
| 561 UNIMPLEMENTED_MIPS(); | 621 UNIMPLEMENTED_MIPS(); |
| 622 __ break_(__LINE__); | |
| 562 } | 623 } |
| 563 | 624 |
| 564 | 625 |
| 565 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { | 626 void CodeGenerator::VisitWhileStatement(WhileStatement* node) { |
| 566 UNIMPLEMENTED_MIPS(); | 627 UNIMPLEMENTED_MIPS(); |
| 628 __ break_(__LINE__); | |
| 567 } | 629 } |
| 568 | 630 |
| 569 | 631 |
| 570 void CodeGenerator::VisitForStatement(ForStatement* node) { | 632 void CodeGenerator::VisitForStatement(ForStatement* node) { |
| 571 UNIMPLEMENTED_MIPS(); | 633 UNIMPLEMENTED_MIPS(); |
| 634 __ break_(__LINE__); | |
| 572 } | 635 } |
| 573 | 636 |
| 574 | 637 |
| 575 void CodeGenerator::VisitForInStatement(ForInStatement* node) { | 638 void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
| 576 UNIMPLEMENTED_MIPS(); | 639 UNIMPLEMENTED_MIPS(); |
| 640 __ break_(__LINE__); | |
| 577 } | 641 } |
| 578 | 642 |
| 579 | 643 |
| 580 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { | 644 void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { |
| 581 UNIMPLEMENTED_MIPS(); | 645 UNIMPLEMENTED_MIPS(); |
| 646 __ break_(__LINE__); | |
| 582 } | 647 } |
| 583 | 648 |
| 584 | 649 |
| 585 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { | 650 void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { |
| 586 UNIMPLEMENTED_MIPS(); | 651 UNIMPLEMENTED_MIPS(); |
| 652 __ break_(__LINE__); | |
| 587 } | 653 } |
| 588 | 654 |
| 589 | 655 |
| 590 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { | 656 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
| 591 UNIMPLEMENTED_MIPS(); | 657 UNIMPLEMENTED_MIPS(); |
| 658 __ break_(__LINE__); | |
| 592 } | 659 } |
| 593 | 660 |
| 594 | 661 |
| 595 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { | 662 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
| 596 UNIMPLEMENTED_MIPS(); | 663 UNIMPLEMENTED_MIPS(); |
| 664 __ break_(__LINE__); | |
| 597 } | 665 } |
| 598 | 666 |
| 599 | 667 |
| 600 void CodeGenerator::VisitSharedFunctionInfoLiteral( | 668 void CodeGenerator::VisitSharedFunctionInfoLiteral( |
| 601 SharedFunctionInfoLiteral* node) { | 669 SharedFunctionInfoLiteral* node) { |
| 602 UNIMPLEMENTED_MIPS(); | 670 UNIMPLEMENTED_MIPS(); |
| 671 __ break_(__LINE__); | |
| 603 } | 672 } |
| 604 | 673 |
| 605 | 674 |
| 606 void CodeGenerator::VisitConditional(Conditional* node) { | 675 void CodeGenerator::VisitConditional(Conditional* node) { |
| 607 UNIMPLEMENTED_MIPS(); | 676 UNIMPLEMENTED_MIPS(); |
| 677 __ break_(__LINE__); | |
| 608 } | 678 } |
| 609 | 679 |
| 610 | 680 |
| 611 void CodeGenerator::VisitSlot(Slot* node) { | 681 void CodeGenerator::VisitSlot(Slot* node) { |
| 612 #ifdef DEBUG | 682 #ifdef DEBUG |
| 613 int original_height = frame_->height(); | 683 int original_height = frame_->height(); |
| 614 #endif | 684 #endif |
| 615 VirtualFrame::SpilledScope spilled_scope; | 685 VirtualFrame::SpilledScope spilled_scope; |
| 616 Comment cmnt(masm_, "[ Slot"); | 686 Comment cmnt(masm_, "[ Slot"); |
| 617 LoadFromSlot(node, typeof_state()); | 687 LoadFromSlot(node, typeof_state()); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 646 VirtualFrame::SpilledScope spilled_scope; | 716 VirtualFrame::SpilledScope spilled_scope; |
| 647 Comment cmnt(masm_, "[ Literal"); | 717 Comment cmnt(masm_, "[ Literal"); |
| 648 __ li(t0, Operand(node->handle())); | 718 __ li(t0, Operand(node->handle())); |
| 649 frame_->EmitPush(t0); | 719 frame_->EmitPush(t0); |
| 650 ASSERT(frame_->height() == original_height + 1); | 720 ASSERT(frame_->height() == original_height + 1); |
| 651 } | 721 } |
| 652 | 722 |
| 653 | 723 |
| 654 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 724 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
| 655 UNIMPLEMENTED_MIPS(); | 725 UNIMPLEMENTED_MIPS(); |
| 726 __ break_(__LINE__); | |
| 656 } | 727 } |
| 657 | 728 |
| 658 | 729 |
| 659 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 730 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
| 660 UNIMPLEMENTED_MIPS(); | 731 UNIMPLEMENTED_MIPS(); |
| 732 __ break_(__LINE__); | |
| 661 } | 733 } |
| 662 | 734 |
| 663 | 735 |
| 664 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 736 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
| 665 UNIMPLEMENTED_MIPS(); | 737 UNIMPLEMENTED_MIPS(); |
| 738 __ break_(__LINE__); | |
| 666 } | 739 } |
| 667 | 740 |
| 668 | 741 |
| 669 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { | 742 void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| 670 UNIMPLEMENTED_MIPS(); | 743 UNIMPLEMENTED_MIPS(); |
| 744 __ break_(__LINE__); | |
| 671 } | 745 } |
| 672 | 746 |
| 673 | 747 |
| 674 void CodeGenerator::VisitAssignment(Assignment* node) { | 748 void CodeGenerator::VisitAssignment(Assignment* node) { |
| 675 #ifdef DEBUG | 749 #ifdef DEBUG |
| 676 int original_height = frame_->height(); | 750 int original_height = frame_->height(); |
| 677 #endif | 751 #endif |
| 678 VirtualFrame::SpilledScope spilled_scope; | 752 VirtualFrame::SpilledScope spilled_scope; |
| 679 Comment cmnt(masm_, "[ Assignment"); | 753 Comment cmnt(masm_, "[ Assignment"); |
| 680 | 754 |
| 681 { Reference target(this, node->target()); | 755 { Reference target(this, node->target(), node->is_compound()); |
| 682 if (target.is_illegal()) { | 756 if (target.is_illegal()) { |
| 683 // Fool the virtual frame into thinking that we left the assignment's | 757 // Fool the virtual frame into thinking that we left the assignment's |
| 684 // value on the frame. | 758 // value on the frame. |
| 685 frame_->EmitPush(zero_reg); | 759 frame_->EmitPush(zero_reg); |
| 686 ASSERT(frame_->height() == original_height + 1); | 760 ASSERT(frame_->height() == original_height + 1); |
| 687 return; | 761 return; |
| 688 } | 762 } |
| 689 | 763 |
| 690 if (node->op() == Token::ASSIGN || | 764 if (node->op() == Token::ASSIGN || |
| 691 node->op() == Token::INIT_VAR || | 765 node->op() == Token::INIT_VAR || |
| 692 node->op() == Token::INIT_CONST) { | 766 node->op() == Token::INIT_CONST) { |
| 693 LoadAndSpill(node->value()); | 767 LoadAndSpill(node->value()); |
| 694 } else { | 768 } else { |
| 695 UNIMPLEMENTED_MIPS(); | 769 UNIMPLEMENTED_MIPS(); |
| 770 __ break_(__LINE__); | |
| 696 } | 771 } |
| 697 | 772 |
| 698 Variable* var = node->target()->AsVariableProxy()->AsVariable(); | 773 Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
| 699 if (var != NULL && | 774 if (var != NULL && |
| 700 (var->mode() == Variable::CONST) && | 775 (var->mode() == Variable::CONST) && |
| 701 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | 776 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { |
| 702 // Assignment ignored - leave the value on the stack. | 777 // Assignment ignored - leave the value on the stack. |
| 703 } else { | 778 } else { |
| 704 CodeForSourcePosition(node->position()); | 779 CodeForSourcePosition(node->position()); |
| 705 if (node->op() == Token::INIT_CONST) { | 780 if (node->op() == Token::INIT_CONST) { |
| 706 // Dynamic constant initializations must use the function context | 781 // Dynamic constant initializations must use the function context |
| 707 // and initialize the actual constant declared. Dynamic variable | 782 // and initialize the actual constant declared. Dynamic variable |
| 708 // initializations are simply assignments and use SetValue. | 783 // initializations are simply assignments and use SetValue. |
| 709 target.SetValue(CONST_INIT); | 784 target.SetValue(CONST_INIT); |
| 710 } else { | 785 } else { |
| 711 target.SetValue(NOT_CONST_INIT); | 786 target.SetValue(NOT_CONST_INIT); |
| 712 } | 787 } |
| 713 } | 788 } |
| 714 } | 789 } |
| 715 ASSERT(frame_->height() == original_height + 1); | 790 ASSERT(frame_->height() == original_height + 1); |
| 716 } | 791 } |
| 717 | 792 |
| 718 | 793 |
| 719 void CodeGenerator::VisitThrow(Throw* node) { | 794 void CodeGenerator::VisitThrow(Throw* node) { |
| 720 UNIMPLEMENTED_MIPS(); | 795 UNIMPLEMENTED_MIPS(); |
| 796 __ break_(__LINE__); | |
| 721 } | 797 } |
| 722 | 798 |
| 723 | 799 |
| 724 void CodeGenerator::VisitProperty(Property* node) { | 800 void CodeGenerator::VisitProperty(Property* node) { |
| 725 UNIMPLEMENTED_MIPS(); | 801 UNIMPLEMENTED_MIPS(); |
| 802 __ break_(__LINE__); | |
| 726 } | 803 } |
| 727 | 804 |
| 728 | 805 |
| 729 void CodeGenerator::VisitCall(Call* node) { | 806 void CodeGenerator::VisitCall(Call* node) { |
| 730 #ifdef DEBUG | 807 #ifdef DEBUG |
| 731 int original_height = frame_->height(); | 808 int original_height = frame_->height(); |
| 732 #endif | 809 #endif |
| 733 VirtualFrame::SpilledScope spilled_scope; | 810 VirtualFrame::SpilledScope spilled_scope; |
| 734 Comment cmnt(masm_, "[ Call"); | 811 Comment cmnt(masm_, "[ Call"); |
| 735 | 812 |
| 736 Expression* function = node->expression(); | 813 Expression* function = node->expression(); |
| 737 ZoneList<Expression*>* args = node->arguments(); | 814 ZoneList<Expression*>* args = node->arguments(); |
| 738 | 815 |
| 739 // Standard function call. | 816 // Standard function call. |
| 740 // Check if the function is a variable or a property. | 817 // Check if the function is a variable or a property. |
| 741 Variable* var = function->AsVariableProxy()->AsVariable(); | 818 Variable* var = function->AsVariableProxy()->AsVariable(); |
| 742 Property* property = function->AsProperty(); | 819 Property* property = function->AsProperty(); |
| 743 | 820 |
| 744 // ------------------------------------------------------------------------ | 821 // ------------------------------------------------------------------------ |
| 745 // Fast-case: Use inline caching. | 822 // Fast-case: Use inline caching. |
| 746 // --- | 823 // --- |
| 747 // According to ECMA-262, section 11.2.3, page 44, the function to call | 824 // According to ECMA-262, section 11.2.3, page 44, the function to call |
| 748 // must be resolved after the arguments have been evaluated. The IC code | 825 // must be resolved after the arguments have been evaluated. The IC code |
| 749 // automatically handles this by loading the arguments before the function | 826 // automatically handles this by loading the arguments before the function |
| 750 // is resolved in cache misses (this also holds for megamorphic calls). | 827 // is resolved in cache misses (this also holds for megamorphic calls). |
| 751 // ------------------------------------------------------------------------ | 828 // ------------------------------------------------------------------------ |
| 752 | 829 |
| 753 if (var != NULL && var->is_possibly_eval()) { | 830 if (var != NULL && var->is_possibly_eval()) { |
| 754 UNIMPLEMENTED_MIPS(); | 831 UNIMPLEMENTED_MIPS(); |
| 832 __ break_(__LINE__); | |
| 755 } else if (var != NULL && !var->is_this() && var->is_global()) { | 833 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 756 // ---------------------------------- | 834 // ----------------------------------------------------- |
| 757 // JavaScript example: 'foo(1, 2, 3)' // foo is global | 835 // JavaScript example: 'foo(1, 2, 3)' // foo is global. |
| 758 // ---------------------------------- | 836 // ----------------------------------------------------- |
| 759 | |
| 760 int arg_count = args->length(); | |
| 761 | |
| 762 // We need sp to be 8 bytes aligned when calling the stub. | |
| 763 __ SetupAlignedCall(t0, arg_count); | |
| 764 | 837 |
| 765 // Pass the global object as the receiver and let the IC stub | 838 // Pass the global object as the receiver and let the IC stub |
| 766 // patch the stack to use the global proxy as 'this' in the | 839 // patch the stack to use the global proxy as 'this' in the |
| 767 // invoked function. | 840 // invoked function. |
| 768 LoadGlobal(); | 841 LoadGlobal(); |
| 769 | 842 |
| 770 // Load the arguments. | 843 // Load the arguments. |
| 844 int arg_count = args->length(); | |
| 771 for (int i = 0; i < arg_count; i++) { | 845 for (int i = 0; i < arg_count; i++) { |
| 772 LoadAndSpill(args->at(i)); | 846 LoadAndSpill(args->at(i)); |
| 773 } | 847 } |
| 774 | 848 |
| 775 // Setup the receiver register and call the IC initialization code. | 849 // Setup the receiver register and call the IC initialization code. |
| 776 __ li(a2, Operand(var->name())); | 850 __ li(a2, Operand(var->name())); |
| 777 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; | 851 InLoopFlag in_loop = loop_nesting() > 0 ? IN_LOOP : NOT_IN_LOOP; |
| 778 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); | 852 Handle<Code> stub = ComputeCallInitialize(arg_count, in_loop); |
| 779 CodeForSourcePosition(node->position()); | 853 CodeForSourcePosition(node->position()); |
| 780 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, | 854 frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
| 781 arg_count + 1); | 855 arg_count + 1); |
| 782 __ ReturnFromAlignedCall(); | |
| 783 __ lw(cp, frame_->Context()); | 856 __ lw(cp, frame_->Context()); |
| 784 // Remove the function from the stack. | 857 // Remove the function from the stack. |
| 785 frame_->EmitPush(v0); | 858 frame_->EmitPush(v0); |
| 786 | 859 |
| 787 } else if (var != NULL && var->slot() != NULL && | 860 } else if (var != NULL && var->slot() != NULL && |
| 788 var->slot()->type() == Slot::LOOKUP) { | 861 var->slot()->type() == Slot::LOOKUP) { |
| 789 UNIMPLEMENTED_MIPS(); | 862 UNIMPLEMENTED_MIPS(); |
| 790 } else if (property != NULL) { | 863 } else if (property != NULL) { |
| 791 UNIMPLEMENTED_MIPS(); | 864 UNIMPLEMENTED_MIPS(); |
| 865 __ break_(__LINE__); | |
| 792 } else { | 866 } else { |
| 793 UNIMPLEMENTED_MIPS(); | 867 UNIMPLEMENTED_MIPS(); |
| 868 __ break_(__LINE__); | |
| 794 } | 869 } |
| 795 | 870 |
| 796 ASSERT(frame_->height() == original_height + 1); | 871 ASSERT(frame_->height() == original_height + 1); |
| 797 } | 872 } |
| 798 | 873 |
| 799 | 874 |
| 800 void CodeGenerator::VisitCallNew(CallNew* node) { | 875 void CodeGenerator::VisitCallNew(CallNew* node) { |
| 801 UNIMPLEMENTED_MIPS(); | 876 UNIMPLEMENTED_MIPS(); |
| 877 __ break_(__LINE__); | |
| 802 } | 878 } |
| 803 | 879 |
| 804 | 880 |
| 805 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { | 881 void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
| 806 UNIMPLEMENTED_MIPS(); | 882 UNIMPLEMENTED_MIPS(); |
| 883 __ break_(__LINE__); | |
| 807 } | 884 } |
| 808 | 885 |
| 809 | 886 |
| 810 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 887 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
| 811 UNIMPLEMENTED_MIPS(); | 888 UNIMPLEMENTED_MIPS(); |
| 889 __ break_(__LINE__); | |
| 812 } | 890 } |
| 813 | 891 |
| 814 | 892 |
| 815 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { | 893 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { |
| 816 UNIMPLEMENTED_MIPS(); | 894 UNIMPLEMENTED_MIPS(); |
| 895 __ break_(__LINE__); | |
| 817 } | 896 } |
| 818 | 897 |
| 819 | 898 |
| 820 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 899 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
| 821 UNIMPLEMENTED_MIPS(); | 900 UNIMPLEMENTED_MIPS(); |
| 901 __ break_(__LINE__); | |
| 822 } | 902 } |
| 823 | 903 |
| 824 | 904 |
| 825 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { | 905 void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { |
| 826 UNIMPLEMENTED_MIPS(); | 906 UNIMPLEMENTED_MIPS(); |
| 907 __ break_(__LINE__); | |
| 827 } | 908 } |
| 828 | 909 |
| 829 | 910 |
| 830 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 911 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
| 831 UNIMPLEMENTED_MIPS(); | 912 UNIMPLEMENTED_MIPS(); |
| 913 __ break_(__LINE__); | |
| 832 } | 914 } |
| 833 | 915 |
| 834 | 916 |
| 835 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { | 917 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { |
| 836 UNIMPLEMENTED_MIPS(); | 918 UNIMPLEMENTED_MIPS(); |
| 919 __ break_(__LINE__); | |
| 837 } | 920 } |
| 838 | 921 |
| 839 | 922 |
| 840 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { | 923 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| 841 UNIMPLEMENTED_MIPS(); | 924 UNIMPLEMENTED_MIPS(); |
| 925 __ break_(__LINE__); | |
| 842 } | 926 } |
| 843 | 927 |
| 844 | 928 |
| 845 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { | 929 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| 846 UNIMPLEMENTED_MIPS(); | 930 UNIMPLEMENTED_MIPS(); |
| 931 __ break_(__LINE__); | |
| 847 } | 932 } |
| 848 | 933 |
| 849 | 934 |
| 850 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { | 935 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
| 851 UNIMPLEMENTED_MIPS(); | 936 UNIMPLEMENTED_MIPS(); |
| 852 } | 937 __ break_(__LINE__); |
| 853 | 938 } |
| 854 | 939 |
| 855 // This should generate code that performs a charCodeAt() call or returns | 940 |
| 856 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. | |
| 857 // It is not yet implemented on ARM, so it always goes to the slow case. | |
| 858 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { | 941 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { |
| 859 UNIMPLEMENTED_MIPS(); | 942 UNIMPLEMENTED_MIPS(); |
| 943 __ break_(__LINE__); | |
| 860 } | 944 } |
| 861 | 945 |
| 862 | 946 |
| 863 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { | 947 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { |
| 864 UNIMPLEMENTED_MIPS(); | 948 UNIMPLEMENTED_MIPS(); |
| 949 __ break_(__LINE__); | |
| 865 } | 950 } |
| 866 | 951 |
| 867 | 952 |
| 868 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | 953 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { |
| 869 UNIMPLEMENTED_MIPS(); | 954 UNIMPLEMENTED_MIPS(); |
| 955 __ break_(__LINE__); | |
| 870 } | 956 } |
| 871 | 957 |
| 872 | 958 |
| 873 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { | 959 void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { |
| 874 UNIMPLEMENTED_MIPS(); | 960 UNIMPLEMENTED_MIPS(); |
| 961 __ break_(__LINE__); | |
| 875 } | 962 } |
| 876 | 963 |
| 877 | 964 |
| 878 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { | 965 void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { |
| 879 UNIMPLEMENTED_MIPS(); | 966 UNIMPLEMENTED_MIPS(); |
| 967 __ break_(__LINE__); | |
| 880 } | 968 } |
| 881 | 969 |
| 882 | 970 |
| 883 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 971 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
| 884 UNIMPLEMENTED_MIPS(); | 972 UNIMPLEMENTED_MIPS(); |
| 973 __ break_(__LINE__); | |
| 885 } | 974 } |
| 886 | 975 |
| 887 | 976 |
| 888 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { | 977 void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { |
| 889 UNIMPLEMENTED_MIPS(); | 978 UNIMPLEMENTED_MIPS(); |
| 979 __ break_(__LINE__); | |
| 890 } | 980 } |
| 891 | 981 |
| 892 | 982 |
| 893 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { | 983 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { |
| 894 UNIMPLEMENTED_MIPS(); | 984 UNIMPLEMENTED_MIPS(); |
| 985 __ break_(__LINE__); | |
| 895 } | 986 } |
| 896 | 987 |
| 897 | 988 |
| 898 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 989 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| 899 UNIMPLEMENTED_MIPS(); | 990 UNIMPLEMENTED_MIPS(); |
| 991 __ break_(__LINE__); | |
| 900 } | 992 } |
| 901 | 993 |
| 902 | 994 |
| 903 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { | 995 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { |
| 904 UNIMPLEMENTED_MIPS(); | 996 UNIMPLEMENTED_MIPS(); |
| 997 __ break_(__LINE__); | |
| 905 } | 998 } |
| 906 | 999 |
| 907 | 1000 |
| 908 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { | 1001 void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
| 909 UNIMPLEMENTED_MIPS(); | 1002 UNIMPLEMENTED_MIPS(); |
| 1003 __ break_(__LINE__); | |
| 910 } | 1004 } |
| 911 | 1005 |
| 912 | 1006 |
| 913 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { | 1007 void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { |
| 914 UNIMPLEMENTED_MIPS(); | 1008 UNIMPLEMENTED_MIPS(); |
| 1009 __ break_(__LINE__); | |
| 915 } | 1010 } |
| 916 | 1011 |
| 917 | 1012 |
| 918 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { | 1013 void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { |
| 919 UNIMPLEMENTED_MIPS(); | 1014 UNIMPLEMENTED_MIPS(); |
| 1015 __ break_(__LINE__); | |
| 920 } | 1016 } |
| 921 | 1017 |
| 922 | 1018 |
| 923 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { | 1019 void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { |
| 924 UNIMPLEMENTED_MIPS(); | 1020 UNIMPLEMENTED_MIPS(); |
| 1021 __ break_(__LINE__); | |
| 925 } | 1022 } |
| 926 | 1023 |
| 927 | 1024 |
| 928 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { | 1025 void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { |
| 929 UNIMPLEMENTED_MIPS(); | 1026 UNIMPLEMENTED_MIPS(); |
| 1027 __ break_(__LINE__); | |
| 930 } | 1028 } |
| 931 | 1029 |
| 932 | 1030 |
| 933 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { | 1031 void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
| 934 UNIMPLEMENTED_MIPS(); | 1032 UNIMPLEMENTED_MIPS(); |
| 1033 __ break_(__LINE__); | |
| 935 } | 1034 } |
| 936 | 1035 |
| 937 | 1036 |
| 938 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { | 1037 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
| 939 UNIMPLEMENTED_MIPS(); | 1038 UNIMPLEMENTED_MIPS(); |
| 1039 __ break_(__LINE__); | |
| 940 } | 1040 } |
| 941 | 1041 |
| 942 | 1042 |
| 943 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { | 1043 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
| 944 UNIMPLEMENTED_MIPS(); | 1044 UNIMPLEMENTED_MIPS(); |
| 1045 __ break_(__LINE__); | |
| 945 } | 1046 } |
| 946 | 1047 |
| 947 | 1048 |
| 948 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 1049 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
| 949 UNIMPLEMENTED_MIPS(); | 1050 UNIMPLEMENTED_MIPS(); |
| 1051 __ break_(__LINE__); | |
| 950 } | 1052 } |
| 951 | 1053 |
| 952 | 1054 |
| 953 void CodeGenerator::VisitCountOperation(CountOperation* node) { | 1055 void CodeGenerator::VisitCountOperation(CountOperation* node) { |
| 954 UNIMPLEMENTED_MIPS(); | 1056 UNIMPLEMENTED_MIPS(); |
| 1057 __ break_(__LINE__); | |
| 955 } | 1058 } |
| 956 | 1059 |
| 957 | 1060 |
| 958 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { | 1061 void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
| 959 UNIMPLEMENTED_MIPS(); | 1062 UNIMPLEMENTED_MIPS(); |
| 960 } | 1063 __ break_(__LINE__); |
| 961 | 1064 } |
| 962 | 1065 |
| 963 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 1066 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
| 964 UNIMPLEMENTED_MIPS(); | 1067 UNIMPLEMENTED_MIPS(); |
| 1068 __ break_(__LINE__); | |
| 965 } | 1069 } |
| 966 | 1070 |
| 967 | 1071 |
| 968 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 1072 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
| 969 UNIMPLEMENTED_MIPS(); | 1073 UNIMPLEMENTED_MIPS(); |
| 970 } | 1074 __ break_(__LINE__); |
| 971 | 1075 } |
| 972 | 1076 |
| 1077 | |
| 973 #ifdef DEBUG | 1078 #ifdef DEBUG |
| 974 bool CodeGenerator::HasValidEntryRegisters() { return true; } | 1079 bool CodeGenerator::HasValidEntryRegisters() { return true; } |
| 975 #endif | 1080 #endif |
| 976 | 1081 |
| 977 | 1082 |
| 978 #undef __ | 1083 #undef __ |
| 979 #define __ ACCESS_MASM(masm) | 1084 #define __ ACCESS_MASM(masm) |
| 980 | 1085 |
| 981 // ----------------------------------------------------------------------------- | 1086 // ----------------------------------------------------------------------------- |
| 982 // Reference support | 1087 // Reference support. |
| 983 | 1088 |
| 984 Reference::Reference(CodeGenerator* cgen, | 1089 Reference::Reference(CodeGenerator* cgen, |
| 985 Expression* expression, | 1090 Expression* expression, |
| 986 bool persist_after_get) | 1091 bool persist_after_get) |
| 987 : cgen_(cgen), | 1092 : cgen_(cgen), |
| 988 expression_(expression), | 1093 expression_(expression), |
| 989 type_(ILLEGAL), | 1094 type_(ILLEGAL), |
| 990 persist_after_get_(persist_after_get) { | 1095 persist_after_get_(persist_after_get) { |
| 991 cgen->LoadReference(this); | 1096 cgen->LoadReference(this); |
| 992 } | 1097 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1072 UNIMPLEMENTED_MIPS(); | 1177 UNIMPLEMENTED_MIPS(); |
| 1073 break; | 1178 break; |
| 1074 } | 1179 } |
| 1075 | 1180 |
| 1076 default: | 1181 default: |
| 1077 UNREACHABLE(); | 1182 UNREACHABLE(); |
| 1078 } | 1183 } |
| 1079 } | 1184 } |
| 1080 | 1185 |
| 1081 | 1186 |
| 1082 // On entry a0 and a1 are the things to be compared. On exit v0 is 0, | |
| 1083 // positive or negative to indicate the result of the comparison. | |
| 1084 void CompareStub::Generate(MacroAssembler* masm) { | 1187 void CompareStub::Generate(MacroAssembler* masm) { |
| 1085 UNIMPLEMENTED_MIPS(); | 1188 UNIMPLEMENTED_MIPS(); |
| 1086 __ break_(0x765); | 1189 __ break_(__LINE__); |
| 1087 } | 1190 } |
| 1088 | 1191 |
| 1089 | 1192 |
| 1090 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { | 1193 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { |
| 1091 UNIMPLEMENTED_MIPS(); | 1194 UNIMPLEMENTED_MIPS(); |
| 1092 return Handle<Code>::null(); | 1195 return Handle<Code>::null(); |
| 1093 } | 1196 } |
| 1094 | 1197 |
| 1095 | 1198 |
| 1096 void StackCheckStub::Generate(MacroAssembler* masm) { | 1199 void StackCheckStub::Generate(MacroAssembler* masm) { |
| 1097 UNIMPLEMENTED_MIPS(); | 1200 UNIMPLEMENTED_MIPS(); |
| 1098 __ break_(0x790); | 1201 __ break_(__LINE__); |
| 1202 } | |
| 1203 | |
| 1204 | |
| 1205 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { | |
| 1206 UNIMPLEMENTED_MIPS(); | |
| 1207 __ break_(__LINE__); | |
| 1099 } | 1208 } |
| 1100 | 1209 |
| 1101 | 1210 |
| 1102 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { | 1211 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| 1103 UNIMPLEMENTED_MIPS(); | 1212 // v0 holds the exception. |
| 1104 __ break_(0x808); | 1213 |
| 1214 // Adjust this code if not the case. | |
| 1215 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | |
| 1216 | |
| 1217 // Drop the sp to the top of the handler. | |
| 1218 __ li(a3, Operand(ExternalReference(Top::k_handler_address))); | |
| 1219 __ lw(sp, MemOperand(a3)); | |
| 1220 | |
| 1221 // Restore the next handler and frame pointer, discard handler state. | |
| 1222 ASSERT(StackHandlerConstants::kNextOffset == 0); | |
| 1223 __ Pop(a2); | |
| 1224 __ sw(a2, MemOperand(a3)); | |
| 1225 ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); | |
| 1226 __ MultiPop(a3.bit() | fp.bit()); | |
| 1227 | |
| 1228 // Before returning we restore the context from the frame pointer if | |
| 1229 // not NULL. The frame pointer is NULL in the exception handler of a | |
| 1230 // JS entry frame. | |
| 1231 // Set cp to NULL if fp is NULL. | |
| 1232 Label done; | |
| 1233 __ Branch(false, &done, eq, fp, Operand(zero_reg)); | |
| 1234 __ mov(cp, zero_reg); // Use the branch delay slot. | |
| 1235 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
| 1236 __ bind(&done); | |
| 1237 | |
| 1238 #ifdef DEBUG | |
| 1239 // TODO(MIPS): Implement debug code. | |
| 1240 #endif | |
| 1241 | |
| 1242 ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); | |
| 1243 __ Pop(t9); | |
| 1244 __ Jump(t9); | |
| 1105 } | 1245 } |
| 1106 | 1246 |
| 1107 | 1247 |
| 1108 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, | 1248 void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| 1109 UncatchableExceptionType type) { | 1249 UncatchableExceptionType type) { |
| 1110 UNIMPLEMENTED_MIPS(); | 1250 UNIMPLEMENTED_MIPS(); |
| 1111 __ break_(0x815); | 1251 __ break_(__LINE__); |
| 1112 } | 1252 } |
| 1113 | 1253 |
| 1114 void CEntryStub::GenerateCore(MacroAssembler* masm, | 1254 void CEntryStub::GenerateCore(MacroAssembler* masm, |
| 1115 Label* throw_normal_exception, | 1255 Label* throw_normal_exception, |
| 1116 Label* throw_termination_exception, | 1256 Label* throw_termination_exception, |
| 1117 Label* throw_out_of_memory_exception, | 1257 Label* throw_out_of_memory_exception, |
| 1118 bool do_gc, | 1258 bool do_gc, |
| 1119 bool always_allocate) { | 1259 bool always_allocate) { |
| 1260 // v0: result parameter for PerformGC, if any | |
| 1120 // s0: number of arguments including receiver (C callee-saved) | 1261 // s0: number of arguments including receiver (C callee-saved) |
| 1121 // s1: pointer to the first argument (C callee-saved) | 1262 // s1: pointer to the first argument (C callee-saved) |
| 1122 // s2: pointer to builtin function (C callee-saved) | 1263 // s2: pointer to builtin function (C callee-saved) |
| 1123 | 1264 |
| 1124 if (do_gc) { | 1265 if (do_gc) { |
| 1125 UNIMPLEMENTED_MIPS(); | 1266 UNIMPLEMENTED_MIPS(); |
| 1267 __ break_(__LINE__); | |
| 1126 } | 1268 } |
| 1127 | 1269 |
| 1128 ExternalReference scope_depth = | 1270 ExternalReference scope_depth = |
| 1129 ExternalReference::heap_always_allocate_scope_depth(); | 1271 ExternalReference::heap_always_allocate_scope_depth(); |
| 1130 if (always_allocate) { | 1272 if (always_allocate) { |
| 1131 UNIMPLEMENTED_MIPS(); | 1273 UNIMPLEMENTED_MIPS(); |
| 1274 __ break_(__LINE__); | |
| 1132 } | 1275 } |
| 1133 | 1276 |
| 1134 // Call C built-in. | 1277 // Call C built-in. |
| 1135 // a0 = argc, a1 = argv | 1278 // a0 = argc, a1 = argv |
| 1136 __ mov(a0, s0); | 1279 __ mov(a0, s0); |
| 1137 __ mov(a1, s1); | 1280 __ mov(a1, s1); |
| 1138 | 1281 |
| 1139 __ CallBuiltin(s2); | 1282 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We |
| 1283 // also need the argument slots. | |
| 1284 __ jalr(s2); | |
| 1285 __ addiu(sp, sp, -StandardFrameConstants::kCArgsSlotsSize); | |
|
Søren Thygesen Gjesse
2010/05/25 09:00:56
Please add a comment on the usage of the branch de
| |
| 1286 __ addiu(sp, sp, StandardFrameConstants::kCArgsSlotsSize); | |
| 1140 | 1287 |
| 1141 if (always_allocate) { | 1288 if (always_allocate) { |
| 1142 UNIMPLEMENTED_MIPS(); | 1289 UNIMPLEMENTED_MIPS(); |
| 1290 __ break_(__LINE__); | |
| 1143 } | 1291 } |
| 1144 | 1292 |
| 1145 // Check for failure result. | 1293 // Check for failure result. |
| 1146 Label failure_returned; | 1294 Label failure_returned; |
| 1147 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 1295 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
| 1148 __ addiu(a2, v0, 1); | 1296 __ addiu(a2, v0, 1); |
| 1149 __ andi(t0, a2, kFailureTagMask); | 1297 __ andi(t0, a2, kFailureTagMask); |
| 1150 __ Branch(eq, &failure_returned, t0, Operand(zero_reg)); | 1298 __ Branch(&failure_returned, eq, t0, Operand(zero_reg)); |
| 1151 | 1299 |
| 1152 // Exit C frame and return. | 1300 // Exit C frame and return. |
| 1153 // v0:v1: result | 1301 // v0:v1: result |
| 1154 // sp: stack pointer | 1302 // sp: stack pointer |
| 1155 // fp: frame pointer | 1303 // fp: frame pointer |
| 1156 __ LeaveExitFrame(mode_); | 1304 __ LeaveExitFrame(mode_); |
| 1157 | 1305 |
| 1158 // Check if we should retry or throw exception. | 1306 // Check if we should retry or throw exception. |
| 1159 Label retry; | 1307 Label retry; |
| 1160 __ bind(&failure_returned); | 1308 __ bind(&failure_returned); |
| 1161 ASSERT(Failure::RETRY_AFTER_GC == 0); | 1309 ASSERT(Failure::RETRY_AFTER_GC == 0); |
| 1162 __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize); | 1310 __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize); |
| 1163 __ Branch(eq, &retry, t0, Operand(zero_reg)); | 1311 __ Branch(&retry, eq, t0, Operand(zero_reg)); |
| 1164 | 1312 |
| 1165 // Special handling of out of memory exceptions. | 1313 // Special handling of out of memory exceptions. |
| 1166 Failure* out_of_memory = Failure::OutOfMemoryException(); | 1314 Failure* out_of_memory = Failure::OutOfMemoryException(); |
| 1167 __ Branch(eq, throw_out_of_memory_exception, | 1315 __ Branch(throw_out_of_memory_exception, eq, |
| 1168 v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); | 1316 v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| 1169 | 1317 |
| 1170 // Retrieve the pending exception and clear the variable. | 1318 // Retrieve the pending exception and clear the variable. |
| 1171 __ LoadExternalReference(t0, ExternalReference::the_hole_value_location()); | 1319 __ LoadExternalReference(t0, ExternalReference::the_hole_value_location()); |
| 1172 __ lw(a3, MemOperand(t0)); | 1320 __ lw(a3, MemOperand(t0)); |
| 1173 __ LoadExternalReference(t0, | 1321 __ LoadExternalReference(t0, |
| 1174 ExternalReference(Top::k_pending_exception_address)); | 1322 ExternalReference(Top::k_pending_exception_address)); |
| 1175 __ lw(v0, MemOperand(t0)); | 1323 __ lw(v0, MemOperand(t0)); |
| 1176 __ sw(a3, MemOperand(t0)); | 1324 __ sw(a3, MemOperand(t0)); |
| 1177 | 1325 |
| 1178 // Special handling of termination exceptions which are uncatchable | 1326 // Special handling of termination exceptions which are uncatchable |
| 1179 // by javascript code. | 1327 // by javascript code. |
| 1180 __ Branch(eq, throw_termination_exception, | 1328 __ Branch(throw_termination_exception, eq, |
| 1181 v0, Operand(Factory::termination_exception())); | 1329 v0, Operand(Factory::termination_exception())); |
| 1182 | 1330 |
| 1183 // Handle normal exception. | 1331 // Handle normal exception. |
| 1184 __ b(throw_normal_exception); | 1332 __ jmp(throw_normal_exception); |
| 1185 __ nop(); // Branch delay slot nop. | |
| 1186 | 1333 |
| 1187 __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying | 1334 __ bind(&retry); |
| 1335 // Last failure (v0) will be moved to (a0) for parameter when retrying. | |
| 1188 } | 1336 } |
| 1189 | 1337 |
| 1190 void CEntryStub::Generate(MacroAssembler* masm) { | 1338 void CEntryStub::Generate(MacroAssembler* masm) { |
| 1191 // Called from JavaScript; parameters are on stack as if calling JS function | 1339 // Called from JavaScript; parameters are on stack as if calling JS function |
| 1192 // a0: number of arguments including receiver | 1340 // a0: number of arguments including receiver |
| 1193 // a1: pointer to builtin function | 1341 // a1: pointer to builtin function |
| 1194 // fp: frame pointer (restored after C call) | 1342 // fp: frame pointer (restored after C call) |
| 1195 // sp: stack pointer (restored as callee's sp after C call) | 1343 // sp: stack pointer (restored as callee's sp after C call) |
| 1196 // cp: current context (C callee-saved) | 1344 // cp: current context (C callee-saved) |
| 1197 | 1345 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1256 // a2: reveiver | 1404 // a2: reveiver |
| 1257 // a3: argc | 1405 // a3: argc |
| 1258 // | 1406 // |
| 1259 // Stack: | 1407 // Stack: |
| 1260 // 4 args slots | 1408 // 4 args slots |
| 1261 // args | 1409 // args |
| 1262 | 1410 |
| 1263 // Save callee saved registers on the stack. | 1411 // Save callee saved registers on the stack. |
| 1264 __ MultiPush((kCalleeSaved | ra.bit()) & ~sp.bit()); | 1412 __ MultiPush((kCalleeSaved | ra.bit()) & ~sp.bit()); |
| 1265 | 1413 |
| 1414 // Load argv in s0 register. | |
| 1415 __ lw(s0, MemOperand(sp, kNumCalleeSaved * kPointerSize + | |
| 1416 StandardFrameConstants::kCArgsSlotsSize)); | |
| 1417 | |
| 1266 // We build an EntryFrame. | 1418 // We build an EntryFrame. |
| 1267 __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. | 1419 __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. |
| 1268 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; | 1420 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
| 1269 __ li(t2, Operand(Smi::FromInt(marker))); | 1421 __ li(t2, Operand(Smi::FromInt(marker))); |
| 1270 __ li(t1, Operand(Smi::FromInt(marker))); | 1422 __ li(t1, Operand(Smi::FromInt(marker))); |
| 1271 __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address)); | 1423 __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address)); |
| 1272 __ lw(t0, MemOperand(t0)); | 1424 __ lw(t0, MemOperand(t0)); |
| 1273 __ MultiPush(t0.bit() | t1.bit() | t2.bit() | t3.bit()); | 1425 __ MultiPush(t0.bit() | t1.bit() | t2.bit() | t3.bit()); |
| 1274 | 1426 |
| 1275 // Setup frame pointer for the frame to be pushed. | 1427 // Setup frame pointer for the frame to be pushed. |
| 1276 __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); | 1428 __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); |
| 1277 | 1429 |
| 1278 // Load argv in s0 register. | |
| 1279 __ lw(s0, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize + | |
| 1280 StandardFrameConstants::kCArgsSlotsSize)); | |
| 1281 | |
| 1282 // Registers: | 1430 // Registers: |
| 1283 // a0: entry_address | 1431 // a0: entry_address |
| 1284 // a1: function | 1432 // a1: function |
| 1285 // a2: reveiver_pointer | 1433 // a2: reveiver_pointer |
| 1286 // a3: argc | 1434 // a3: argc |
| 1287 // s0: argv | 1435 // s0: argv |
| 1288 // | 1436 // |
| 1289 // Stack: | 1437 // Stack: |
| 1290 // caller fp | | 1438 // caller fp | |
| 1291 // function slot | entry frame | 1439 // function slot | entry frame |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1343 // 4 args slots | 1491 // 4 args slots |
| 1344 // args | 1492 // args |
| 1345 | 1493 |
| 1346 if (is_construct) { | 1494 if (is_construct) { |
| 1347 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); | 1495 ExternalReference construct_entry(Builtins::JSConstructEntryTrampoline); |
| 1348 __ LoadExternalReference(t0, construct_entry); | 1496 __ LoadExternalReference(t0, construct_entry); |
| 1349 } else { | 1497 } else { |
| 1350 ExternalReference entry(Builtins::JSEntryTrampoline); | 1498 ExternalReference entry(Builtins::JSEntryTrampoline); |
| 1351 __ LoadExternalReference(t0, entry); | 1499 __ LoadExternalReference(t0, entry); |
| 1352 } | 1500 } |
| 1353 __ lw(t9, MemOperand(t0)); // deref address | 1501 __ lw(t9, MemOperand(t0)); // Deref address. |
| 1354 | 1502 |
| 1355 // Call JSEntryTrampoline. | 1503 // Call JSEntryTrampoline. |
| 1356 __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); | 1504 __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); |
| 1357 __ CallBuiltin(t9); | 1505 __ CallBuiltin(t9); |
| 1358 | 1506 |
| 1359 // Unlink this frame from the handler chain. When reading the | 1507 // Unlink this frame from the handler chain. When reading the |
| 1360 // address of the next handler, there is no need to use the address | 1508 // address of the next handler, there is no need to use the address |
| 1361 // displacement since the current stack pointer (sp) points directly | 1509 // displacement since the current stack pointer (sp) points directly |
| 1362 // to the stack handler. | 1510 // to the stack handler. |
| 1363 __ lw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); | 1511 __ lw(t1, MemOperand(sp, StackHandlerConstants::kNextOffset)); |
| 1364 __ LoadExternalReference(t0, ExternalReference(Top::k_handler_address)); | 1512 __ LoadExternalReference(t0, ExternalReference(Top::k_handler_address)); |
| 1365 __ sw(t1, MemOperand(t0)); | 1513 __ sw(t1, MemOperand(t0)); |
| 1366 | 1514 |
| 1367 // This restores sp to its position before PushTryHandler. | 1515 // This restores sp to its position before PushTryHandler. |
| 1368 __ addiu(sp, sp, StackHandlerConstants::kSize); | 1516 __ addiu(sp, sp, StackHandlerConstants::kSize); |
| 1369 | 1517 |
| 1370 __ bind(&exit); // v0 holds result | 1518 __ bind(&exit); // v0 holds result. |
| 1371 // Restore the top frame descriptors from the stack. | 1519 // Restore the top frame descriptors from the stack. |
| 1372 __ Pop(t1); | 1520 __ Pop(t1); |
| 1373 __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address)); | 1521 __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address)); |
| 1374 __ sw(t1, MemOperand(t0)); | 1522 __ sw(t1, MemOperand(t0)); |
| 1375 | 1523 |
| 1376 // Reset the stack to the callee saved registers. | 1524 // Reset the stack to the callee saved registers. |
| 1377 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); | 1525 __ addiu(sp, sp, -EntryFrameConstants::kCallerFPOffset); |
| 1378 | 1526 |
| 1379 // Restore callee saved registers from the stack. | 1527 // Restore callee saved registers from the stack. |
| 1380 __ MultiPop((kCalleeSaved | ra.bit()) & ~sp.bit()); | 1528 __ MultiPop((kCalleeSaved | ra.bit()) & ~sp.bit()); |
| 1381 // Return. | 1529 // Return. |
| 1382 __ Jump(ra); | 1530 __ Jump(ra); |
| 1383 } | 1531 } |
| 1384 | 1532 |
| 1385 | 1533 |
| 1386 // This stub performs an instanceof, calling the builtin function if | 1534 // This stub performs an instanceof, calling the builtin function if |
| 1387 // necessary. Uses a1 for the object, a0 for the function that it may | 1535 // necessary. Uses a1 for the object, a0 for the function that it may |
| 1388 // be an instance of (these are fetched from the stack). | 1536 // be an instance of (these are fetched from the stack). |
| 1389 void InstanceofStub::Generate(MacroAssembler* masm) { | 1537 void InstanceofStub::Generate(MacroAssembler* masm) { |
| 1390 UNIMPLEMENTED_MIPS(); | 1538 UNIMPLEMENTED_MIPS(); |
| 1391 __ break_(0x845); | 1539 __ break_(0x845); |
| 1392 } | 1540 } |
| 1393 | 1541 |
| 1394 | 1542 |
| 1395 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { | 1543 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
| 1396 UNIMPLEMENTED_MIPS(); | 1544 UNIMPLEMENTED_MIPS(); |
| 1397 __ break_(0x851); | 1545 __ break_(__LINE__); |
| 1398 } | 1546 } |
| 1399 | 1547 |
| 1400 | 1548 |
| 1401 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { | 1549 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| 1402 UNIMPLEMENTED_MIPS(); | 1550 UNIMPLEMENTED_MIPS(); |
| 1403 __ break_(0x857); | 1551 __ break_(__LINE__); |
| 1404 } | 1552 } |
| 1405 | 1553 |
| 1406 | 1554 |
| 1407 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { | 1555 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { |
| 1408 UNIMPLEMENTED_MIPS(); | 1556 UNIMPLEMENTED_MIPS(); |
| 1409 __ break_(0x863); | 1557 __ break_(__LINE__); |
| 1410 } | 1558 } |
| 1411 | 1559 |
| 1412 | 1560 |
| 1413 const char* CompareStub::GetName() { | 1561 const char* CompareStub::GetName() { |
| 1414 UNIMPLEMENTED_MIPS(); | 1562 UNIMPLEMENTED_MIPS(); |
| 1415 return NULL; // UNIMPLEMENTED RETURN | 1563 return NULL; // UNIMPLEMENTED RETURN. |
| 1416 } | 1564 } |
| 1417 | 1565 |
| 1418 | 1566 |
| 1419 int CompareStub::MinorKey() { | 1567 int CompareStub::MinorKey() { |
| 1420 // Encode the two parameters in a unique 16 bit value. | 1568 // Encode the two parameters in a unique 16 bit value. |
| 1421 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); | 1569 ASSERT(static_cast<unsigned>(cc_) >> 28 < (1 << 15)); |
| 1422 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); | 1570 return (static_cast<unsigned>(cc_) >> 27) | (strict_ ? 1 : 0); |
| 1423 } | 1571 } |
| 1424 | 1572 |
| 1425 | 1573 |
| 1426 #undef __ | 1574 #undef __ |
| 1427 | 1575 |
| 1428 } } // namespace v8::internal | 1576 } } // namespace v8::internal |
| OLD | NEW |