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