Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 17 matching lines...) Expand all Loading... | |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
| 31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
| 32 #include "debug.h" | 32 #include "debug.h" |
| 33 #include "scopes.h" | 33 #include "scopes.h" |
| 34 #include "runtime.h" | 34 #include "runtime.h" |
| 35 | 35 |
| 36 namespace v8 { namespace internal { | 36 namespace v8 { namespace internal { |
| 37 | 37 |
| 38 #define __ masm_-> | |
| 39 | |
| 40 // ------------------------------------------------------------------------- | |
| 41 // VirtualFrame implementation. | |
| 42 | |
| 43 VirtualFrame::VirtualFrame(CodeGenerator* cgen) { | |
| 44 ASSERT(cgen->scope() != NULL); | |
| 45 | |
| 46 masm_ = cgen->masm(); | |
| 47 frame_local_count_ = cgen->scope()->num_stack_slots(); | |
| 48 parameter_count_ = cgen->scope()->num_parameters(); | |
| 49 } | |
| 50 | |
| 51 | |
| 38 // ------------------------------------------------------------------------- | 52 // ------------------------------------------------------------------------- |
| 39 // CodeGenState implementation. | 53 // CodeGenState implementation. |
| 40 | 54 |
| 41 CodeGenState::CodeGenState(CodeGenerator* owner) | 55 CodeGenState::CodeGenState(CodeGenerator* owner) |
| 42 : owner_(owner), | 56 : owner_(owner), |
| 43 typeof_state_(NOT_INSIDE_TYPEOF), | 57 typeof_state_(NOT_INSIDE_TYPEOF), |
| 44 true_target_(NULL), | 58 true_target_(NULL), |
| 45 false_target_(NULL), | 59 false_target_(NULL), |
| 46 previous_(NULL) { | 60 previous_(NULL) { |
| 47 owner_->set_state(this); | 61 owner_->set_state(this); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 60 owner_->set_state(this); | 74 owner_->set_state(this); |
| 61 } | 75 } |
| 62 | 76 |
| 63 | 77 |
| 64 CodeGenState::~CodeGenState() { | 78 CodeGenState::~CodeGenState() { |
| 65 ASSERT(owner_->state() == this); | 79 ASSERT(owner_->state() == this); |
| 66 owner_->set_state(previous_); | 80 owner_->set_state(previous_); |
| 67 } | 81 } |
| 68 | 82 |
| 69 | 83 |
| 70 // ----------------------------------------------------------------------------- | 84 // ------------------------------------------------------------------------- |
| 71 // CodeGenerator implementation | 85 // CodeGenerator implementation |
| 72 | 86 |
| 73 #define __ masm_-> | |
| 74 | |
| 75 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, | 87 CodeGenerator::CodeGenerator(int buffer_size, Handle<Script> script, |
| 76 bool is_eval) | 88 bool is_eval) |
| 77 : is_eval_(is_eval), | 89 : is_eval_(is_eval), |
| 78 script_(script), | 90 script_(script), |
| 79 deferred_(8), | 91 deferred_(8), |
| 80 masm_(new MacroAssembler(NULL, buffer_size)), | 92 masm_(new MacroAssembler(NULL, buffer_size)), |
| 81 scope_(NULL), | 93 scope_(NULL), |
| 94 frame_(NULL), | |
| 82 cc_reg_(al), | 95 cc_reg_(al), |
| 83 state_(NULL), | 96 state_(NULL), |
| 84 break_stack_height_(0) { | 97 break_stack_height_(0) { |
| 85 } | 98 } |
| 86 | 99 |
| 87 | 100 |
| 88 // Calling conventions: | 101 // Calling conventions: |
| 89 | 102 |
| 90 // r0: the number of arguments | 103 // r0: the number of arguments |
| 91 // fp: frame pointer | 104 // fp: frame pointer |
| 92 // sp: stack pointer | 105 // sp: stack pointer |
| 93 // pp: caller's parameter pointer | 106 // pp: caller's parameter pointer |
| 94 // cp: callee's context | 107 // cp: callee's context |
| 95 | 108 |
| 96 void CodeGenerator::GenCode(FunctionLiteral* fun) { | 109 void CodeGenerator::GenCode(FunctionLiteral* fun) { |
| 97 Scope* scope = fun->scope(); | |
| 98 ZoneList<Statement*>* body = fun->body(); | 110 ZoneList<Statement*>* body = fun->body(); |
| 99 | 111 |
| 100 // Initialize state. | 112 // Initialize state. |
| 101 { CodeGenState state(this); | 113 ASSERT(scope_ == NULL); |
| 102 scope_ = scope; | 114 scope_ = fun->scope(); |
| 103 cc_reg_ = al; | 115 ASSERT(frame_ == NULL); |
| 116 VirtualFrame virtual_frame(this); | |
| 117 frame_ = &virtual_frame; | |
| 118 cc_reg_ = al; | |
| 119 { | |
| 120 CodeGenState state(this); | |
| 104 | 121 |
| 105 // Entry | 122 // Entry |
| 106 // stack: function, receiver, arguments, return address | 123 // stack: function, receiver, arguments, return address |
| 107 // r0: number of arguments | 124 // r0: number of arguments |
| 108 // sp: stack pointer | 125 // sp: stack pointer |
| 109 // fp: frame pointer | 126 // fp: frame pointer |
| 110 // pp: caller's parameter pointer | 127 // pp: caller's parameter pointer |
| 111 // cp: callee's context | 128 // cp: callee's context |
| 112 | 129 |
| 113 { Comment cmnt(masm_, "[ enter JS frame"); | 130 { Comment cmnt(masm_, "[ enter JS frame"); |
| 114 EnterJSFrame(); | 131 EnterJSFrame(); |
| 115 } | 132 } |
| 116 // tos: code slot | 133 // tos: code slot |
| 117 #ifdef DEBUG | 134 #ifdef DEBUG |
| 118 if (strlen(FLAG_stop_at) > 0 && | 135 if (strlen(FLAG_stop_at) > 0 && |
| 119 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 136 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
| 120 __ stop("stop-at"); | 137 __ stop("stop-at"); |
| 121 } | 138 } |
| 122 #endif | 139 #endif |
| 123 | 140 |
| 124 // Allocate space for locals and initialize them. | 141 // Allocate space for locals and initialize them. |
| 125 if (scope->num_stack_slots() > 0) { | 142 if (scope_->num_stack_slots() > 0) { |
| 126 Comment cmnt(masm_, "[ allocate space for locals"); | 143 Comment cmnt(masm_, "[ allocate space for locals"); |
| 127 // Initialize stack slots with 'undefined' value. | 144 // Initialize stack slots with 'undefined' value. |
| 128 __ mov(ip, Operand(Factory::undefined_value())); | 145 __ mov(ip, Operand(Factory::undefined_value())); |
| 129 for (int i = 0; i < scope->num_stack_slots(); i++) { | 146 for (int i = 0; i < scope_->num_stack_slots(); i++) { |
| 130 __ push(ip); | 147 __ push(ip); |
| 131 } | 148 } |
| 132 } | 149 } |
| 133 | 150 |
| 134 if (scope->num_heap_slots() > 0) { | 151 if (scope_->num_heap_slots() > 0) { |
| 135 // Allocate local context. | 152 // Allocate local context. |
| 136 // Get outer context and create a new context based on it. | 153 // Get outer context and create a new context based on it. |
| 137 __ ldr(r0, FunctionOperand()); | 154 __ ldr(r0, frame_->Function()); |
| 138 __ push(r0); | 155 __ push(r0); |
| 139 __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result | 156 __ CallRuntime(Runtime::kNewContext, 1); // r0 holds the result |
| 140 | 157 |
| 141 if (kDebug) { | 158 if (kDebug) { |
| 142 Label verified_true; | 159 Label verified_true; |
| 143 __ cmp(r0, Operand(cp)); | 160 __ cmp(r0, Operand(cp)); |
| 144 __ b(eq, &verified_true); | 161 __ b(eq, &verified_true); |
| 145 __ stop("NewContext: r0 is expected to be the same as cp"); | 162 __ stop("NewContext: r0 is expected to be the same as cp"); |
| 146 __ bind(&verified_true); | 163 __ bind(&verified_true); |
| 147 } | 164 } |
| 148 // Update context local. | 165 // Update context local. |
| 149 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 166 __ str(cp, frame_->Context()); |
| 150 } | 167 } |
| 151 | 168 |
| 152 // TODO(1241774): Improve this code!!! | 169 // TODO(1241774): Improve this code!!! |
| 153 // 1) only needed if we have a context | 170 // 1) only needed if we have a context |
| 154 // 2) no need to recompute context ptr every single time | 171 // 2) no need to recompute context ptr every single time |
| 155 // 3) don't copy parameter operand code from SlotOperand! | 172 // 3) don't copy parameter operand code from SlotOperand! |
| 156 { | 173 { |
| 157 Comment cmnt2(masm_, "[ copy context parameters into .context"); | 174 Comment cmnt2(masm_, "[ copy context parameters into .context"); |
| 158 | 175 |
| 159 // Note that iteration order is relevant here! If we have the same | 176 // Note that iteration order is relevant here! If we have the same |
| 160 // parameter twice (e.g., function (x, y, x)), and that parameter | 177 // parameter twice (e.g., function (x, y, x)), and that parameter |
| 161 // needs to be copied into the context, it must be the last argument | 178 // needs to be copied into the context, it must be the last argument |
| 162 // passed to the parameter that needs to be copied. This is a rare | 179 // passed to the parameter that needs to be copied. This is a rare |
| 163 // case so we don't check for it, instead we rely on the copying | 180 // case so we don't check for it, instead we rely on the copying |
| 164 // order: such a parameter is copied repeatedly into the same | 181 // order: such a parameter is copied repeatedly into the same |
| 165 // context location and thus the last value is what is seen inside | 182 // context location and thus the last value is what is seen inside |
| 166 // the function. | 183 // the function. |
| 167 for (int i = 0; i < scope->num_parameters(); i++) { | 184 for (int i = 0; i < scope_->num_parameters(); i++) { |
| 168 Variable* par = scope->parameter(i); | 185 Variable* par = scope_->parameter(i); |
| 169 Slot* slot = par->slot(); | 186 Slot* slot = par->slot(); |
| 170 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 187 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 171 ASSERT(!scope->is_global_scope()); // no parameters in global scope | 188 ASSERT(!scope_->is_global_scope()); // no parameters in global scope |
| 172 __ ldr(r1, ParameterOperand(i)); | 189 __ ldr(r1, frame_->Parameter(i)); |
| 173 // Loads r2 with context; used below in RecordWrite. | 190 // Loads r2 with context; used below in RecordWrite. |
| 174 __ str(r1, SlotOperand(slot, r2)); | 191 __ str(r1, SlotOperand(slot, r2)); |
| 175 // Load the offset into r3. | 192 // Load the offset into r3. |
| 176 int slot_offset = | 193 int slot_offset = |
| 177 FixedArray::kHeaderSize + slot->index() * kPointerSize; | 194 FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 178 __ mov(r3, Operand(slot_offset)); | 195 __ mov(r3, Operand(slot_offset)); |
| 179 __ RecordWrite(r2, r3, r1); | 196 __ RecordWrite(r2, r3, r1); |
| 180 } | 197 } |
| 181 } | 198 } |
| 182 } | 199 } |
| 183 | 200 |
| 184 // Store the arguments object. | 201 // Store the arguments object. |
| 185 // This must happen after context initialization because | 202 // This must happen after context initialization because |
| 186 // the arguments array may be stored in the context! | 203 // the arguments array may be stored in the context! |
| 187 if (scope->arguments() != NULL) { | 204 if (scope_->arguments() != NULL) { |
| 188 ASSERT(scope->arguments_shadow() != NULL); | 205 ASSERT(scope_->arguments_shadow() != NULL); |
| 189 Comment cmnt(masm_, "[ allocate arguments object"); | 206 Comment cmnt(masm_, "[ allocate arguments object"); |
| 190 { Reference shadow_ref(this, scope->arguments_shadow()); | 207 { Reference shadow_ref(this, scope_->arguments_shadow()); |
| 191 { Reference arguments_ref(this, scope->arguments()); | 208 { Reference arguments_ref(this, scope_->arguments()); |
| 192 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); | 209 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); |
| 193 __ ldr(r2, FunctionOperand()); | 210 __ ldr(r2, frame_->Function()); |
| 194 // The receiver is below the arguments, the return address, | 211 // The receiver is below the arguments, the return address, |
| 195 // and the frame pointer on the stack. | 212 // and the frame pointer on the stack. |
| 196 const int kReceiverDisplacement = 2 + scope->num_parameters(); | 213 const int kReceiverDisplacement = 2 + scope_->num_parameters(); |
| 197 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); | 214 __ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize)); |
| 198 __ mov(r0, Operand(Smi::FromInt(scope->num_parameters()))); | 215 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); |
| 199 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); | 216 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit()); |
| 200 __ CallStub(&stub); | 217 __ CallStub(&stub); |
|
Kevin Millikin (Chromium)
2008/11/04 08:39:59
This is the only place that "ReceiverOperand" woul
| |
| 201 __ push(r0); | 218 __ push(r0); |
| 202 arguments_ref.SetValue(NOT_CONST_INIT); | 219 arguments_ref.SetValue(NOT_CONST_INIT); |
| 203 } | 220 } |
| 204 shadow_ref.SetValue(NOT_CONST_INIT); | 221 shadow_ref.SetValue(NOT_CONST_INIT); |
| 205 } | 222 } |
| 206 __ pop(r0); // Value is no longer needed. | 223 __ pop(r0); // Value is no longer needed. |
| 207 } | 224 } |
| 208 | 225 |
| 209 // Generate code to 'execute' declarations and initialize | 226 // Generate code to 'execute' declarations and initialize |
| 210 // functions (source elements). In case of an illegal | 227 // functions (source elements). In case of an illegal |
| 211 // redeclaration we need to handle that instead of processing the | 228 // redeclaration we need to handle that instead of processing the |
| 212 // declarations. | 229 // declarations. |
| 213 if (scope->HasIllegalRedeclaration()) { | 230 if (scope_->HasIllegalRedeclaration()) { |
| 214 Comment cmnt(masm_, "[ illegal redeclarations"); | 231 Comment cmnt(masm_, "[ illegal redeclarations"); |
| 215 scope->VisitIllegalRedeclaration(this); | 232 scope_->VisitIllegalRedeclaration(this); |
| 216 } else { | 233 } else { |
| 217 Comment cmnt(masm_, "[ declarations"); | 234 Comment cmnt(masm_, "[ declarations"); |
| 218 // ProcessDeclarations calls DeclareGlobals indirectly | 235 // ProcessDeclarations calls DeclareGlobals indirectly |
| 219 ProcessDeclarations(scope->declarations()); | 236 ProcessDeclarations(scope_->declarations()); |
| 220 | 237 |
| 221 // Bail out if a stack-overflow exception occurred when | 238 // Bail out if a stack-overflow exception occurred when |
| 222 // processing declarations. | 239 // processing declarations. |
| 223 if (HasStackOverflow()) return; | 240 if (HasStackOverflow()) return; |
| 224 } | 241 } |
| 225 | 242 |
| 226 if (FLAG_trace) { | 243 if (FLAG_trace) { |
| 227 // Push a valid value as the parameter. The runtime call only uses | 244 // Push a valid value as the parameter. The runtime call only uses |
| 228 // it as the return value to indicate non-failure. | 245 // it as the return value to indicate non-failure. |
| 229 __ CallRuntime(Runtime::kTraceEnter, 0); | 246 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 230 } | 247 } |
| 231 CheckStack(); | 248 CheckStack(); |
| 232 | 249 |
| 233 // Compile the body of the function in a vanilla state. Don't | 250 // Compile the body of the function in a vanilla state. Don't |
| 234 // bother compiling all the code if the scope has an illegal | 251 // bother compiling all the code if the scope has an illegal |
| 235 // redeclaration. | 252 // redeclaration. |
| 236 if (!scope->HasIllegalRedeclaration()) { | 253 if (!scope_->HasIllegalRedeclaration()) { |
| 237 Comment cmnt(masm_, "[ function body"); | 254 Comment cmnt(masm_, "[ function body"); |
| 238 #ifdef DEBUG | 255 #ifdef DEBUG |
| 239 bool is_builtin = Bootstrapper::IsActive(); | 256 bool is_builtin = Bootstrapper::IsActive(); |
| 240 bool should_trace = | 257 bool should_trace = |
| 241 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; | 258 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
| 242 if (should_trace) { | 259 if (should_trace) { |
| 243 __ CallRuntime(Runtime::kDebugTrace, 0); | 260 __ CallRuntime(Runtime::kDebugTrace, 0); |
| 244 } | 261 } |
| 245 #endif | 262 #endif |
| 246 VisitStatements(body); | 263 VisitStatements(body); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 265 | 282 |
| 266 // Tear down the frame which will restore the caller's frame pointer and the | 283 // Tear down the frame which will restore the caller's frame pointer and the |
| 267 // link register. | 284 // link register. |
| 268 ExitJSFrame(); | 285 ExitJSFrame(); |
| 269 | 286 |
| 270 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); | 287 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize)); |
| 271 __ mov(pc, lr); | 288 __ mov(pc, lr); |
| 272 | 289 |
| 273 // Code generation state must be reset. | 290 // Code generation state must be reset. |
| 274 scope_ = NULL; | 291 scope_ = NULL; |
| 292 frame_ = NULL; | |
| 275 ASSERT(!has_cc()); | 293 ASSERT(!has_cc()); |
| 276 ASSERT(state_ == NULL); | 294 ASSERT(state_ == NULL); |
| 277 } | 295 } |
| 278 | 296 |
| 279 | 297 |
| 280 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { | 298 MemOperand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { |
| 281 // Currently, this assertion will fail if we try to assign to | 299 // Currently, this assertion will fail if we try to assign to |
| 282 // a constant variable that is constant because it is read-only | 300 // a constant variable that is constant because it is read-only |
| 283 // (such as the variable referring to a named function expression). | 301 // (such as the variable referring to a named function expression). |
| 284 // We need to implement assignments to read-only variables. | 302 // We need to implement assignments to read-only variables. |
| 285 // Ideally, we should do this during AST generation (by converting | 303 // Ideally, we should do this during AST generation (by converting |
| 286 // such assignments into expression statements); however, in general | 304 // such assignments into expression statements); however, in general |
| 287 // we may not be able to make the decision until past AST generation, | 305 // we may not be able to make the decision until past AST generation, |
| 288 // that is when the entire program is known. | 306 // that is when the entire program is known. |
| 289 ASSERT(slot != NULL); | 307 ASSERT(slot != NULL); |
| 290 int index = slot->index(); | 308 int index = slot->index(); |
| 291 switch (slot->type()) { | 309 switch (slot->type()) { |
| 292 case Slot::PARAMETER: | 310 case Slot::PARAMETER: |
| 293 return ParameterOperand(index); | 311 return frame_->Parameter(index); |
| 294 | 312 |
| 295 case Slot::LOCAL: { | 313 case Slot::LOCAL: |
| 296 ASSERT(0 <= index && index < scope()->num_stack_slots()); | 314 return frame_->Local(index); |
| 297 const int kLocalOffset = JavaScriptFrameConstants::kLocal0Offset; | |
| 298 return MemOperand(fp, kLocalOffset - index * kPointerSize); | |
| 299 } | |
| 300 | 315 |
| 301 case Slot::CONTEXT: { | 316 case Slot::CONTEXT: { |
| 302 // Follow the context chain if necessary. | 317 // Follow the context chain if necessary. |
| 303 ASSERT(!tmp.is(cp)); // do not overwrite context register | 318 ASSERT(!tmp.is(cp)); // do not overwrite context register |
| 304 Register context = cp; | 319 Register context = cp; |
| 305 int chain_length = scope()->ContextChainLength(slot->var()->scope()); | 320 int chain_length = scope()->ContextChainLength(slot->var()->scope()); |
| 306 for (int i = chain_length; i-- > 0;) { | 321 for (int i = chain_length; i-- > 0;) { |
| 307 // Load the closure. | 322 // Load the closure. |
| 308 // (All contexts, even 'with' contexts, have a closure, | 323 // (All contexts, even 'with' contexts, have a closure, |
| 309 // and it is the same for all contexts inside a function. | 324 // and it is the same for all contexts inside a function. |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 972 } | 987 } |
| 973 | 988 |
| 974 // Record the position for debugging purposes. | 989 // Record the position for debugging purposes. |
| 975 __ RecordPosition(position); | 990 __ RecordPosition(position); |
| 976 | 991 |
| 977 // Use the shared code stub to call the function. | 992 // Use the shared code stub to call the function. |
| 978 CallFunctionStub call_function(args->length()); | 993 CallFunctionStub call_function(args->length()); |
| 979 __ CallStub(&call_function); | 994 __ CallStub(&call_function); |
| 980 | 995 |
| 981 // Restore context and pop function from the stack. | 996 // Restore context and pop function from the stack. |
| 982 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 997 __ ldr(cp, frame_->Context()); |
| 983 __ pop(); // discard the TOS | 998 __ pop(); // discard the TOS |
| 984 } | 999 } |
| 985 | 1000 |
| 986 | 1001 |
| 987 void CodeGenerator::Branch(bool if_true, Label* L) { | 1002 void CodeGenerator::Branch(bool if_true, Label* L) { |
| 988 ASSERT(has_cc()); | 1003 ASSERT(has_cc()); |
| 989 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); | 1004 Condition cc = if_true ? cc_reg_ : NegateCondition(cc_reg_); |
| 990 __ b(cc, L); | 1005 __ b(cc, L); |
| 991 cc_reg_ = al; | 1006 cc_reg_ = al; |
| 992 } | 1007 } |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1207 Load(node->expression()); | 1222 Load(node->expression()); |
| 1208 __ CallRuntime(Runtime::kPushContext, 1); | 1223 __ CallRuntime(Runtime::kPushContext, 1); |
| 1209 if (kDebug) { | 1224 if (kDebug) { |
| 1210 Label verified_true; | 1225 Label verified_true; |
| 1211 __ cmp(r0, Operand(cp)); | 1226 __ cmp(r0, Operand(cp)); |
| 1212 __ b(eq, &verified_true); | 1227 __ b(eq, &verified_true); |
| 1213 __ stop("PushContext: r0 is expected to be the same as cp"); | 1228 __ stop("PushContext: r0 is expected to be the same as cp"); |
| 1214 __ bind(&verified_true); | 1229 __ bind(&verified_true); |
| 1215 } | 1230 } |
| 1216 // Update context local. | 1231 // Update context local. |
| 1217 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1232 __ str(cp, frame_->Context()); |
| 1218 } | 1233 } |
| 1219 | 1234 |
| 1220 | 1235 |
| 1221 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { | 1236 void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
| 1222 Comment cmnt(masm_, "[ WithExitStatement"); | 1237 Comment cmnt(masm_, "[ WithExitStatement"); |
| 1223 // Pop context. | 1238 // Pop context. |
| 1224 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); | 1239 __ ldr(cp, ContextOperand(cp, Context::PREVIOUS_INDEX)); |
| 1225 // Update context local. | 1240 // Update context local. |
| 1226 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1241 __ str(cp, frame_->Context()); |
| 1227 } | 1242 } |
| 1228 | 1243 |
| 1229 | 1244 |
| 1230 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { | 1245 int CodeGenerator::FastCaseSwitchMaxOverheadFactor() { |
| 1231 return kFastSwitchMaxOverheadFactor; | 1246 return kFastSwitchMaxOverheadFactor; |
| 1232 } | 1247 } |
| 1233 | 1248 |
| 1234 int CodeGenerator::FastCaseSwitchMinCaseCount() { | 1249 int CodeGenerator::FastCaseSwitchMinCaseCount() { |
| 1235 return kFastSwitchMinCaseCount; | 1250 return kFastSwitchMinCaseCount; |
| 1236 } | 1251 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1317 // statements if it does not match any of the cases. | 1332 // statements if it does not match any of the cases. |
| 1318 __ b(&next); | 1333 __ b(&next); |
| 1319 | 1334 |
| 1320 // Bind the default case label, so we can branch to it when we | 1335 // Bind the default case label, so we can branch to it when we |
| 1321 // have compared against all other cases. | 1336 // have compared against all other cases. |
| 1322 ASSERT(default_case.is_unused()); // at most one default clause | 1337 ASSERT(default_case.is_unused()); // at most one default clause |
| 1323 __ bind(&default_case); | 1338 __ bind(&default_case); |
| 1324 } else { | 1339 } else { |
| 1325 __ bind(&next); | 1340 __ bind(&next); |
| 1326 next.Unuse(); | 1341 next.Unuse(); |
| 1327 __ ldr(r0, MemOperand(sp, 0)); | 1342 __ ldr(r0, frame_->Top()); |
| 1328 __ push(r0); // duplicate TOS | 1343 __ push(r0); // duplicate TOS |
| 1329 Load(clause->label()); | 1344 Load(clause->label()); |
| 1330 Comparison(eq, true); | 1345 Comparison(eq, true); |
| 1331 Branch(false, &next); | 1346 Branch(false, &next); |
| 1332 } | 1347 } |
| 1333 | 1348 |
| 1334 // Entering the case statement for the first time. Remove the switch value | 1349 // Entering the case statement for the first time. Remove the switch value |
| 1335 // from the stack. | 1350 // from the stack. |
| 1336 __ pop(r0); | 1351 __ pop(r0); |
| 1337 | 1352 |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1536 __ push(r0); | 1551 __ push(r0); |
| 1537 | 1552 |
| 1538 // Condition. | 1553 // Condition. |
| 1539 __ bind(&entry); | 1554 __ bind(&entry); |
| 1540 | 1555 |
| 1541 // sp[0] : index | 1556 // sp[0] : index |
| 1542 // sp[1] : array/enum cache length | 1557 // sp[1] : array/enum cache length |
| 1543 // sp[2] : array or enum cache | 1558 // sp[2] : array or enum cache |
| 1544 // sp[3] : 0 or map | 1559 // sp[3] : 0 or map |
| 1545 // sp[4] : enumerable | 1560 // sp[4] : enumerable |
| 1546 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); // load the current count | 1561 __ ldr(r0, frame_->Element(0)); // load the current count |
| 1547 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); // load the length | 1562 __ ldr(r1, frame_->Element(1)); // load the length |
| 1548 __ cmp(r0, Operand(r1)); // compare to the array length | 1563 __ cmp(r0, Operand(r1)); // compare to the array length |
| 1549 __ b(hs, &cleanup); | 1564 __ b(hs, &cleanup); |
| 1550 | 1565 |
| 1551 __ ldr(r0, MemOperand(sp, 0 * kPointerSize)); | 1566 __ ldr(r0, frame_->Element(0)); |
| 1552 | 1567 |
| 1553 // Get the i'th entry of the array. | 1568 // Get the i'th entry of the array. |
| 1554 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); | 1569 __ ldr(r2, frame_->Element(2)); |
| 1555 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1570 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 1556 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1571 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1557 | 1572 |
| 1558 // Get Map or 0. | 1573 // Get Map or 0. |
| 1559 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); | 1574 __ ldr(r2, frame_->Element(3)); |
| 1560 // Check if this (still) matches the map of the enumerable. | 1575 // Check if this (still) matches the map of the enumerable. |
| 1561 // If not, we have to filter the key. | 1576 // If not, we have to filter the key. |
| 1562 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); | 1577 __ ldr(r1, frame_->Element(4)); |
| 1563 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); | 1578 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 1564 __ cmp(r1, Operand(r2)); | 1579 __ cmp(r1, Operand(r2)); |
| 1565 __ b(eq, &end_del_check); | 1580 __ b(eq, &end_del_check); |
| 1566 | 1581 |
| 1567 // Convert the entry to a string (or null if it isn't a property anymore). | 1582 // Convert the entry to a string (or null if it isn't a property anymore). |
| 1568 __ ldr(r0, MemOperand(sp, 4 * kPointerSize)); // push enumerable | 1583 __ ldr(r0, frame_->Element(4)); // push enumerable |
| 1569 __ push(r0); | 1584 __ push(r0); |
| 1570 __ push(r3); // push entry | 1585 __ push(r3); // push entry |
| 1571 __ mov(r0, Operand(1)); | 1586 __ mov(r0, Operand(1)); |
| 1572 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); | 1587 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS); |
| 1573 __ mov(r3, Operand(r0)); | 1588 __ mov(r3, Operand(r0)); |
| 1574 | 1589 |
| 1575 // If the property has been removed while iterating, we just skip it. | 1590 // If the property has been removed while iterating, we just skip it. |
| 1576 __ cmp(r3, Operand(Factory::null_value())); | 1591 __ cmp(r3, Operand(Factory::null_value())); |
| 1577 __ b(eq, &next); | 1592 __ b(eq, &next); |
| 1578 | 1593 |
| 1579 | 1594 |
| 1580 __ bind(&end_del_check); | 1595 __ bind(&end_del_check); |
| 1581 | 1596 |
| 1582 // Store the entry in the 'each' expression and take another spin in the loop. | 1597 // Store the entry in the 'each' expression and take another spin in the loop. |
| 1583 // r3: i'th entry of the enum cache (or string there of) | 1598 // r3: i'th entry of the enum cache (or string there of) |
| 1584 __ push(r3); // push entry | 1599 __ push(r3); // push entry |
| 1585 { Reference each(this, node->each()); | 1600 { Reference each(this, node->each()); |
| 1586 if (!each.is_illegal()) { | 1601 if (!each.is_illegal()) { |
| 1587 if (each.size() > 0) { | 1602 if (each.size() > 0) { |
| 1588 __ ldr(r0, MemOperand(sp, kPointerSize * each.size())); | 1603 __ ldr(r0, frame_->Element(each.size())); |
| 1589 __ push(r0); | 1604 __ push(r0); |
| 1590 } | 1605 } |
| 1591 // If the reference was to a slot we rely on the convenient property | 1606 // If the reference was to a slot we rely on the convenient property |
| 1592 // that it doesn't matter whether a value (eg, r3 pushed above) is | 1607 // that it doesn't matter whether a value (eg, r3 pushed above) is |
| 1593 // right on top of or right underneath a zero-sized reference. | 1608 // right on top of or right underneath a zero-sized reference. |
| 1594 each.SetValue(NOT_CONST_INIT); | 1609 each.SetValue(NOT_CONST_INIT); |
| 1595 if (each.size() > 0) { | 1610 if (each.size() > 0) { |
| 1596 // It's safe to pop the value lying on top of the reference before | 1611 // It's safe to pop the value lying on top of the reference before |
| 1597 // unloading the reference itself (which preserves the top of stack, | 1612 // unloading the reference itself (which preserves the top of stack, |
| 1598 // ie, now the topmost value of the non-zero sized reference), since | 1613 // ie, now the topmost value of the non-zero sized reference), since |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1673 // After shadowing stops, the original labels are unshadowed and the | 1688 // After shadowing stops, the original labels are unshadowed and the |
| 1674 // LabelShadows represent the formerly shadowing labels. | 1689 // LabelShadows represent the formerly shadowing labels. |
| 1675 int nof_unlinks = 0; | 1690 int nof_unlinks = 0; |
| 1676 for (int i = 0; i <= nof_escapes; i++) { | 1691 for (int i = 0; i <= nof_escapes; i++) { |
| 1677 shadows[i]->StopShadowing(); | 1692 shadows[i]->StopShadowing(); |
| 1678 if (shadows[i]->is_linked()) nof_unlinks++; | 1693 if (shadows[i]->is_linked()) nof_unlinks++; |
| 1679 } | 1694 } |
| 1680 | 1695 |
| 1681 // Unlink from try chain. | 1696 // Unlink from try chain. |
| 1682 // TOS contains code slot | 1697 // TOS contains code slot |
| 1683 const int kNextOffset = StackHandlerConstants::kNextOffset + | 1698 const int kNextIndex = (StackHandlerConstants::kNextOffset |
| 1684 StackHandlerConstants::kAddressDisplacement; | 1699 + StackHandlerConstants::kAddressDisplacement) |
| 1685 __ ldr(r1, MemOperand(sp, kNextOffset)); // read next_sp | 1700 / kPointerSize; |
|
Kevin Millikin (Chromium)
2008/11/04 08:39:59
Changed as per request.
| |
| 1701 __ ldr(r1, frame_->Element(kNextIndex)); // read next_sp | |
| 1686 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1702 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1687 __ str(r1, MemOperand(r3)); | 1703 __ str(r1, MemOperand(r3)); |
| 1688 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1704 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
| 1689 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1705 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 1690 // Code slot popped. | 1706 // Code slot popped. |
| 1691 if (nof_unlinks > 0) __ b(&exit); | 1707 if (nof_unlinks > 0) __ b(&exit); |
| 1692 | 1708 |
| 1693 // Generate unlink code for the (formerly) shadowing labels that have been | 1709 // Generate unlink code for the (formerly) shadowing labels that have been |
| 1694 // jumped to. | 1710 // jumped to. |
| 1695 for (int i = 0; i <= nof_escapes; i++) { | 1711 for (int i = 0; i <= nof_escapes; i++) { |
| 1696 if (shadows[i]->is_linked()) { | 1712 if (shadows[i]->is_linked()) { |
| 1697 // Unlink from try chain; | 1713 // Unlink from try chain; |
| 1698 __ bind(shadows[i]); | 1714 __ bind(shadows[i]); |
| 1699 | 1715 |
| 1700 // Reload sp from the top handler, because some statements that we | 1716 // Reload sp from the top handler, because some statements that we |
| 1701 // break from (eg, for...in) may have left stuff on the stack. | 1717 // break from (eg, for...in) may have left stuff on the stack. |
| 1702 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1718 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1703 __ ldr(sp, MemOperand(r3)); | 1719 __ ldr(sp, MemOperand(r3)); |
| 1704 | 1720 |
| 1705 __ ldr(r1, MemOperand(sp, kNextOffset)); | 1721 __ ldr(r1, frame_->Element(kNextIndex)); |
| 1706 __ str(r1, MemOperand(r3)); | 1722 __ str(r1, MemOperand(r3)); |
| 1707 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1723 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
| 1708 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1724 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 1709 // Code slot popped. | 1725 // Code slot popped. |
| 1710 | 1726 |
| 1711 __ b(shadows[i]->original_label()); | 1727 __ b(shadows[i]->original_label()); |
| 1712 } | 1728 } |
| 1713 } | 1729 } |
| 1714 | 1730 |
| 1715 __ bind(&exit); | 1731 __ bind(&exit); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1790 } | 1806 } |
| 1791 | 1807 |
| 1792 // Unlink from try chain; | 1808 // Unlink from try chain; |
| 1793 __ bind(&unlink); | 1809 __ bind(&unlink); |
| 1794 | 1810 |
| 1795 __ pop(r0); // Store TOS in r0 across stack manipulation | 1811 __ pop(r0); // Store TOS in r0 across stack manipulation |
| 1796 // Reload sp from the top handler, because some statements that we | 1812 // Reload sp from the top handler, because some statements that we |
| 1797 // break from (eg, for...in) may have left stuff on the stack. | 1813 // break from (eg, for...in) may have left stuff on the stack. |
| 1798 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); | 1814 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); |
| 1799 __ ldr(sp, MemOperand(r3)); | 1815 __ ldr(sp, MemOperand(r3)); |
| 1800 const int kNextOffset = StackHandlerConstants::kNextOffset + | 1816 const int kNextIndex = (StackHandlerConstants::kNextOffset |
| 1801 StackHandlerConstants::kAddressDisplacement; | 1817 + StackHandlerConstants::kAddressDisplacement) |
| 1802 __ ldr(r1, MemOperand(sp, kNextOffset)); | 1818 / kPointerSize; |
| 1819 __ ldr(r1, frame_->Element(kNextIndex)); | |
| 1803 __ str(r1, MemOperand(r3)); | 1820 __ str(r1, MemOperand(r3)); |
| 1804 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code | 1821 ASSERT(StackHandlerConstants::kCodeOffset == 0); // first field is code |
| 1805 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); | 1822 __ add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize)); |
| 1806 // Code slot popped. | 1823 // Code slot popped. |
| 1807 __ push(r0); | 1824 __ push(r0); |
| 1808 | 1825 |
| 1809 // --- Finally block --- | 1826 // --- Finally block --- |
| 1810 __ bind(&finally_block); | 1827 __ bind(&finally_block); |
| 1811 | 1828 |
| 1812 // Push the state on the stack. | 1829 // Push the state on the stack. |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1975 __ push(r0); | 1992 __ push(r0); |
| 1976 } | 1993 } |
| 1977 | 1994 |
| 1978 | 1995 |
| 1979 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { | 1996 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
| 1980 Comment cmnt(masm_, "[ RexExp Literal"); | 1997 Comment cmnt(masm_, "[ RexExp Literal"); |
| 1981 | 1998 |
| 1982 // Retrieve the literal array and check the allocated entry. | 1999 // Retrieve the literal array and check the allocated entry. |
| 1983 | 2000 |
| 1984 // Load the function of this activation. | 2001 // Load the function of this activation. |
| 1985 __ ldr(r1, FunctionOperand()); | 2002 __ ldr(r1, frame_->Function()); |
| 1986 | 2003 |
| 1987 // Load the literals array of the function. | 2004 // Load the literals array of the function. |
| 1988 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 2005 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
| 1989 | 2006 |
| 1990 // Load the literal at the ast saved index. | 2007 // Load the literal at the ast saved index. |
| 1991 int literal_offset = | 2008 int literal_offset = |
| 1992 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2009 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
| 1993 __ ldr(r2, FieldMemOperand(r1, literal_offset)); | 2010 __ ldr(r2, FieldMemOperand(r1, literal_offset)); |
| 1994 | 2011 |
| 1995 Label done; | 2012 Label done; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2048 | 2065 |
| 2049 | 2066 |
| 2050 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { | 2067 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
| 2051 Comment cmnt(masm_, "[ ObjectLiteral"); | 2068 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 2052 | 2069 |
| 2053 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); | 2070 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); |
| 2054 | 2071 |
| 2055 // Retrieve the literal array and check the allocated entry. | 2072 // Retrieve the literal array and check the allocated entry. |
| 2056 | 2073 |
| 2057 // Load the function of this activation. | 2074 // Load the function of this activation. |
| 2058 __ ldr(r1, FunctionOperand()); | 2075 __ ldr(r1, frame_->Function()); |
| 2059 | 2076 |
| 2060 // Load the literals array of the function. | 2077 // Load the literals array of the function. |
| 2061 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); | 2078 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); |
| 2062 | 2079 |
| 2063 // Load the literal at the ast saved index. | 2080 // Load the literal at the ast saved index. |
| 2064 int literal_offset = | 2081 int literal_offset = |
| 2065 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2082 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
| 2066 __ ldr(r2, FieldMemOperand(r1, literal_offset)); | 2083 __ ldr(r2, FieldMemOperand(r1, literal_offset)); |
| 2067 | 2084 |
| 2068 // Check whether we need to materialize the object literal boilerplate. | 2085 // Check whether we need to materialize the object literal boilerplate. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2085 Expression* value = property->value(); | 2102 Expression* value = property->value(); |
| 2086 switch (property->kind()) { | 2103 switch (property->kind()) { |
| 2087 case ObjectLiteral::Property::CONSTANT: break; | 2104 case ObjectLiteral::Property::CONSTANT: break; |
| 2088 case ObjectLiteral::Property::COMPUTED: // fall through | 2105 case ObjectLiteral::Property::COMPUTED: // fall through |
| 2089 case ObjectLiteral::Property::PROTOTYPE: { | 2106 case ObjectLiteral::Property::PROTOTYPE: { |
| 2090 __ push(r0); // dup the result | 2107 __ push(r0); // dup the result |
| 2091 Load(key); | 2108 Load(key); |
| 2092 Load(value); | 2109 Load(value); |
| 2093 __ CallRuntime(Runtime::kSetProperty, 3); | 2110 __ CallRuntime(Runtime::kSetProperty, 3); |
| 2094 // restore r0 | 2111 // restore r0 |
| 2095 __ ldr(r0, MemOperand(sp, 0)); | 2112 __ ldr(r0, frame_->Top()); |
| 2096 break; | 2113 break; |
| 2097 } | 2114 } |
| 2098 case ObjectLiteral::Property::SETTER: { | 2115 case ObjectLiteral::Property::SETTER: { |
| 2099 __ push(r0); | 2116 __ push(r0); |
| 2100 Load(key); | 2117 Load(key); |
| 2101 __ mov(r0, Operand(Smi::FromInt(1))); | 2118 __ mov(r0, Operand(Smi::FromInt(1))); |
| 2102 __ push(r0); | 2119 __ push(r0); |
| 2103 Load(value); | 2120 Load(value); |
| 2104 __ CallRuntime(Runtime::kDefineAccessor, 4); | 2121 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 2105 __ ldr(r0, MemOperand(sp, 0)); | 2122 __ ldr(r0, frame_->Top()); |
| 2106 break; | 2123 break; |
| 2107 } | 2124 } |
| 2108 case ObjectLiteral::Property::GETTER: { | 2125 case ObjectLiteral::Property::GETTER: { |
| 2109 __ push(r0); | 2126 __ push(r0); |
| 2110 Load(key); | 2127 Load(key); |
| 2111 __ mov(r0, Operand(Smi::FromInt(0))); | 2128 __ mov(r0, Operand(Smi::FromInt(0))); |
| 2112 __ push(r0); | 2129 __ push(r0); |
| 2113 Load(value); | 2130 Load(value); |
| 2114 __ CallRuntime(Runtime::kDefineAccessor, 4); | 2131 __ CallRuntime(Runtime::kDefineAccessor, 4); |
| 2115 __ ldr(r0, MemOperand(sp, 0)); | 2132 __ ldr(r0, frame_->Top()); |
| 2116 break; | 2133 break; |
| 2117 } | 2134 } |
| 2118 } | 2135 } |
| 2119 } | 2136 } |
| 2120 } | 2137 } |
| 2121 | 2138 |
| 2122 | 2139 |
| 2123 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { | 2140 void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
| 2124 Comment cmnt(masm_, "[ ArrayLiteral"); | 2141 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 2125 | 2142 |
| 2126 // Call runtime to create the array literal. | 2143 // Call runtime to create the array literal. |
| 2127 __ mov(r0, Operand(node->literals())); | 2144 __ mov(r0, Operand(node->literals())); |
| 2128 __ push(r0); | 2145 __ push(r0); |
| 2129 // Load the function of this frame. | 2146 // Load the function of this frame. |
| 2130 __ ldr(r0, FunctionOperand()); | 2147 __ ldr(r0, frame_->Function()); |
| 2131 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 2148 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
| 2132 __ push(r0); | 2149 __ push(r0); |
| 2133 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); | 2150 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); |
| 2134 | 2151 |
| 2135 // Push the resulting array literal on the stack. | 2152 // Push the resulting array literal on the stack. |
| 2136 __ push(r0); | 2153 __ push(r0); |
| 2137 | 2154 |
| 2138 // Generate code to set the elements in the array that are not | 2155 // Generate code to set the elements in the array that are not |
| 2139 // literals. | 2156 // literals. |
| 2140 for (int i = 0; i < node->values()->length(); i++) { | 2157 for (int i = 0; i < node->values()->length(); i++) { |
| 2141 Expression* value = node->values()->at(i); | 2158 Expression* value = node->values()->at(i); |
| 2142 | 2159 |
| 2143 // If value is literal the property value is already | 2160 // If value is literal the property value is already |
| 2144 // set in the boilerplate object. | 2161 // set in the boilerplate object. |
| 2145 if (value->AsLiteral() == NULL) { | 2162 if (value->AsLiteral() == NULL) { |
| 2146 // The property must be set by generated code. | 2163 // The property must be set by generated code. |
| 2147 Load(value); | 2164 Load(value); |
| 2148 __ pop(r0); | 2165 __ pop(r0); |
| 2149 | 2166 |
| 2150 // Fetch the object literal | 2167 // Fetch the object literal |
| 2151 __ ldr(r1, MemOperand(sp, 0)); | 2168 __ ldr(r1, frame_->Top()); |
| 2152 // Get the elements array. | 2169 // Get the elements array. |
| 2153 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 2170 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
| 2154 | 2171 |
| 2155 // Write to the indexed properties array. | 2172 // Write to the indexed properties array. |
| 2156 int offset = i * kPointerSize + Array::kHeaderSize; | 2173 int offset = i * kPointerSize + Array::kHeaderSize; |
| 2157 __ str(r0, FieldMemOperand(r1, offset)); | 2174 __ str(r0, FieldMemOperand(r1, offset)); |
| 2158 | 2175 |
| 2159 // Update the write barrier for the array address. | 2176 // Update the write barrier for the array address. |
| 2160 __ mov(r3, Operand(offset)); | 2177 __ mov(r3, Operand(offset)); |
| 2161 __ RecordWrite(r1, r3, r2); | 2178 __ RecordWrite(r1, r3, r2); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2264 // invoked function. | 2281 // invoked function. |
| 2265 LoadGlobal(); | 2282 LoadGlobal(); |
| 2266 | 2283 |
| 2267 // Load the arguments. | 2284 // Load the arguments. |
| 2268 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2285 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
| 2269 | 2286 |
| 2270 // Setup the receiver register and call the IC initialization code. | 2287 // Setup the receiver register and call the IC initialization code. |
| 2271 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2288 Handle<Code> stub = ComputeCallInitialize(args->length()); |
| 2272 __ RecordPosition(node->position()); | 2289 __ RecordPosition(node->position()); |
| 2273 __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT); | 2290 __ Call(stub, RelocInfo::CODE_TARGET_CONTEXT); |
| 2274 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2291 __ ldr(cp, frame_->Context()); |
| 2275 // Remove the function from the stack. | 2292 // Remove the function from the stack. |
| 2276 __ pop(); | 2293 __ pop(); |
| 2277 __ push(r0); | 2294 __ push(r0); |
| 2278 | 2295 |
| 2279 } else if (var != NULL && var->slot() != NULL && | 2296 } else if (var != NULL && var->slot() != NULL && |
| 2280 var->slot()->type() == Slot::LOOKUP) { | 2297 var->slot()->type() == Slot::LOOKUP) { |
| 2281 // ---------------------------------- | 2298 // ---------------------------------- |
| 2282 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj | 2299 // JavaScript example: 'with (obj) foo(1, 2, 3)' // foo is in obj |
| 2283 // ---------------------------------- | 2300 // ---------------------------------- |
| 2284 | 2301 |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2311 __ push(r0); | 2328 __ push(r0); |
| 2312 Load(property->obj()); | 2329 Load(property->obj()); |
| 2313 | 2330 |
| 2314 // Load the arguments. | 2331 // Load the arguments. |
| 2315 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2332 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
| 2316 | 2333 |
| 2317 // Set the receiver register and call the IC initialization code. | 2334 // Set the receiver register and call the IC initialization code. |
| 2318 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2335 Handle<Code> stub = ComputeCallInitialize(args->length()); |
| 2319 __ RecordPosition(node->position()); | 2336 __ RecordPosition(node->position()); |
| 2320 __ Call(stub, RelocInfo::CODE_TARGET); | 2337 __ Call(stub, RelocInfo::CODE_TARGET); |
| 2321 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2338 __ ldr(cp, frame_->Context()); |
| 2322 | 2339 |
| 2323 // Remove the function from the stack. | 2340 // Remove the function from the stack. |
| 2324 __ pop(); | 2341 __ pop(); |
| 2325 | 2342 |
| 2326 __ push(r0); // push after get rid of function from the stack | 2343 __ push(r0); // push after get rid of function from the stack |
| 2327 | 2344 |
| 2328 } else { | 2345 } else { |
| 2329 // ------------------------------------------- | 2346 // ------------------------------------------- |
| 2330 // JavaScript example: 'array[index](1, 2, 3)' | 2347 // JavaScript example: 'array[index](1, 2, 3)' |
| 2331 // ------------------------------------------- | 2348 // ------------------------------------------- |
| 2332 | 2349 |
| 2333 // Load the function to call from the property through a reference. | 2350 // Load the function to call from the property through a reference. |
| 2334 Reference ref(this, property); | 2351 Reference ref(this, property); |
| 2335 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver | 2352 ref.GetValue(NOT_INSIDE_TYPEOF); // receiver |
| 2336 | 2353 |
| 2337 // Pass receiver to called function. | 2354 // Pass receiver to called function. |
| 2338 __ ldr(r0, MemOperand(sp, ref.size() * kPointerSize)); | 2355 __ ldr(r0, frame_->Element(ref.size())); |
| 2339 __ push(r0); | 2356 __ push(r0); |
| 2340 // Call the function. | 2357 // Call the function. |
| 2341 CallWithArguments(args, node->position()); | 2358 CallWithArguments(args, node->position()); |
| 2342 __ push(r0); | 2359 __ push(r0); |
| 2343 } | 2360 } |
| 2344 | 2361 |
| 2345 } else { | 2362 } else { |
| 2346 // ---------------------------------- | 2363 // ---------------------------------- |
| 2347 // JavaScript example: 'foo(1, 2, 3)' // foo is not global | 2364 // JavaScript example: 'foo(1, 2, 3)' // foo is not global |
| 2348 // ---------------------------------- | 2365 // ---------------------------------- |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2376 LoadGlobal(); | 2393 LoadGlobal(); |
| 2377 | 2394 |
| 2378 // Push the arguments ("left-to-right") on the stack. | 2395 // Push the arguments ("left-to-right") on the stack. |
| 2379 ZoneList<Expression*>* args = node->arguments(); | 2396 ZoneList<Expression*>* args = node->arguments(); |
| 2380 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2397 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
| 2381 | 2398 |
| 2382 // r0: the number of arguments. | 2399 // r0: the number of arguments. |
| 2383 __ mov(r0, Operand(args->length())); | 2400 __ mov(r0, Operand(args->length())); |
| 2384 | 2401 |
| 2385 // Load the function into r1 as per calling convention. | 2402 // Load the function into r1 as per calling convention. |
| 2386 __ ldr(r1, MemOperand(sp, (args->length() + 1) * kPointerSize)); | 2403 __ ldr(r1, frame_->Element(args->length() + 1)); |
| 2387 | 2404 |
| 2388 // Call the construct call builtin that handles allocation and | 2405 // Call the construct call builtin that handles allocation and |
| 2389 // constructor invocation. | 2406 // constructor invocation. |
| 2390 __ RecordPosition(RelocInfo::POSITION); | 2407 __ RecordPosition(RelocInfo::POSITION); |
| 2391 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), | 2408 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), |
| 2392 RelocInfo::CONSTRUCT_CALL); | 2409 RelocInfo::CONSTRUCT_CALL); |
| 2393 | 2410 |
| 2394 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). | 2411 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). |
| 2395 __ str(r0, MemOperand(sp, 0 * kPointerSize)); | 2412 __ str(r0, frame_->Top()); |
| 2396 } | 2413 } |
| 2397 | 2414 |
| 2398 | 2415 |
| 2399 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 2416 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
| 2400 ASSERT(args->length() == 1); | 2417 ASSERT(args->length() == 1); |
| 2401 Label leave; | 2418 Label leave; |
| 2402 Load(args->at(0)); | 2419 Load(args->at(0)); |
| 2403 __ pop(r0); // r0 contains object. | 2420 __ pop(r0); // r0 contains object. |
| 2404 // if (object->IsSmi()) return the object. | 2421 // if (object->IsSmi()) return the object. |
| 2405 __ tst(r0, Operand(kSmiTagMask)); | 2422 __ tst(r0, Operand(kSmiTagMask)); |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2558 // Push the builtins object found in the current global object. | 2575 // Push the builtins object found in the current global object. |
| 2559 __ ldr(r1, GlobalObject()); | 2576 __ ldr(r1, GlobalObject()); |
| 2560 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); | 2577 __ ldr(r0, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); |
| 2561 __ push(r0); | 2578 __ push(r0); |
| 2562 | 2579 |
| 2563 for (int i = 0; i < args->length(); i++) Load(args->at(i)); | 2580 for (int i = 0; i < args->length(); i++) Load(args->at(i)); |
| 2564 | 2581 |
| 2565 // Call the JS runtime function. | 2582 // Call the JS runtime function. |
| 2566 Handle<Code> stub = ComputeCallInitialize(args->length()); | 2583 Handle<Code> stub = ComputeCallInitialize(args->length()); |
| 2567 __ Call(stub, RelocInfo::CODE_TARGET); | 2584 __ Call(stub, RelocInfo::CODE_TARGET); |
| 2568 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2585 __ ldr(cp, frame_->Context()); |
| 2569 __ pop(); | 2586 __ pop(); |
| 2570 __ push(r0); | 2587 __ push(r0); |
| 2571 } | 2588 } |
| 2572 } | 2589 } |
| 2573 | 2590 |
| 2574 | 2591 |
| 2575 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { | 2592 void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
| 2576 Comment cmnt(masm_, "[ UnaryOperation"); | 2593 Comment cmnt(masm_, "[ UnaryOperation"); |
| 2577 | 2594 |
| 2578 Token::Value op = node->op(); | 2595 Token::Value op = node->op(); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2720 Label slow, exit; | 2737 Label slow, exit; |
| 2721 | 2738 |
| 2722 // Load the value (1) into register r1. | 2739 // Load the value (1) into register r1. |
| 2723 __ mov(r1, Operand(Smi::FromInt(1))); | 2740 __ mov(r1, Operand(Smi::FromInt(1))); |
| 2724 | 2741 |
| 2725 // Check for smi operand. | 2742 // Check for smi operand. |
| 2726 __ tst(r0, Operand(kSmiTagMask)); | 2743 __ tst(r0, Operand(kSmiTagMask)); |
| 2727 __ b(ne, &slow); | 2744 __ b(ne, &slow); |
| 2728 | 2745 |
| 2729 // Postfix: Store the old value as the result. | 2746 // Postfix: Store the old value as the result. |
| 2730 if (is_postfix) __ str(r0, MemOperand(sp, target.size() * kPointerSize)); | 2747 if (is_postfix) { |
| 2748 __ str(r0, frame_->Element(target.size())); | |
| 2749 } | |
| 2731 | 2750 |
| 2732 // Perform optimistic increment/decrement. | 2751 // Perform optimistic increment/decrement. |
| 2733 if (is_increment) { | 2752 if (is_increment) { |
| 2734 __ add(r0, r0, Operand(r1), SetCC); | 2753 __ add(r0, r0, Operand(r1), SetCC); |
| 2735 } else { | 2754 } else { |
| 2736 __ sub(r0, r0, Operand(r1), SetCC); | 2755 __ sub(r0, r0, Operand(r1), SetCC); |
| 2737 } | 2756 } |
| 2738 | 2757 |
| 2739 // If the increment/decrement didn't overflow, we're done. | 2758 // If the increment/decrement didn't overflow, we're done. |
| 2740 __ b(vc, &exit); | 2759 __ b(vc, &exit); |
| 2741 | 2760 |
| 2742 // Revert optimistic increment/decrement. | 2761 // Revert optimistic increment/decrement. |
| 2743 if (is_increment) { | 2762 if (is_increment) { |
| 2744 __ sub(r0, r0, Operand(r1)); | 2763 __ sub(r0, r0, Operand(r1)); |
| 2745 } else { | 2764 } else { |
| 2746 __ add(r0, r0, Operand(r1)); | 2765 __ add(r0, r0, Operand(r1)); |
| 2747 } | 2766 } |
| 2748 | 2767 |
| 2749 // Slow case: Convert to number. | 2768 // Slow case: Convert to number. |
| 2750 __ bind(&slow); | 2769 __ bind(&slow); |
| 2751 | 2770 |
| 2752 // Postfix: Convert the operand to a number and store it as the result. | 2771 // Postfix: Convert the operand to a number and store it as the result. |
| 2753 if (is_postfix) { | 2772 if (is_postfix) { |
| 2754 InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2); | 2773 InvokeBuiltinStub stub(InvokeBuiltinStub::ToNumber, 2); |
| 2755 __ CallStub(&stub); | 2774 __ CallStub(&stub); |
| 2756 // Store to result (on the stack). | 2775 // Store to result (on the stack). |
| 2757 __ str(r0, MemOperand(sp, target.size() * kPointerSize)); | 2776 __ str(r0, frame_->Element(target.size())); |
| 2758 } | 2777 } |
| 2759 | 2778 |
| 2760 // Compute the new value by calling the right JavaScript native. | 2779 // Compute the new value by calling the right JavaScript native. |
| 2761 if (is_increment) { | 2780 if (is_increment) { |
| 2762 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1); | 2781 InvokeBuiltinStub stub(InvokeBuiltinStub::Inc, 1); |
| 2763 __ CallStub(&stub); | 2782 __ CallStub(&stub); |
| 2764 } else { | 2783 } else { |
| 2765 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1); | 2784 InvokeBuiltinStub stub(InvokeBuiltinStub::Dec, 1); |
| 2766 __ CallStub(&stub); | 2785 __ CallStub(&stub); |
| 2767 } | 2786 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2807 __ bind(&is_true); | 2826 __ bind(&is_true); |
| 2808 LoadCondition(node->right(), | 2827 LoadCondition(node->right(), |
| 2809 NOT_INSIDE_TYPEOF, | 2828 NOT_INSIDE_TYPEOF, |
| 2810 true_target(), | 2829 true_target(), |
| 2811 false_target(), | 2830 false_target(), |
| 2812 false); | 2831 false); |
| 2813 | 2832 |
| 2814 } else { | 2833 } else { |
| 2815 Label pop_and_continue, exit; | 2834 Label pop_and_continue, exit; |
| 2816 | 2835 |
| 2817 __ ldr(r0, MemOperand(sp, 0)); // dup the stack top | 2836 __ ldr(r0, frame_->Top()); // dup the stack top |
| 2818 __ push(r0); | 2837 __ push(r0); |
| 2819 // Avoid popping the result if it converts to 'false' using the | 2838 // Avoid popping the result if it converts to 'false' using the |
| 2820 // standard ToBoolean() conversion as described in ECMA-262, | 2839 // standard ToBoolean() conversion as described in ECMA-262, |
| 2821 // section 9.2, page 30. | 2840 // section 9.2, page 30. |
| 2822 ToBoolean(&pop_and_continue, &exit); | 2841 ToBoolean(&pop_and_continue, &exit); |
| 2823 Branch(false, &exit); | 2842 Branch(false, &exit); |
| 2824 | 2843 |
| 2825 // Pop the result of evaluating the first part. | 2844 // Pop the result of evaluating the first part. |
| 2826 __ bind(&pop_and_continue); | 2845 __ bind(&pop_and_continue); |
| 2827 __ pop(r0); | 2846 __ pop(r0); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 2848 __ bind(&is_false); | 2867 __ bind(&is_false); |
| 2849 LoadCondition(node->right(), | 2868 LoadCondition(node->right(), |
| 2850 NOT_INSIDE_TYPEOF, | 2869 NOT_INSIDE_TYPEOF, |
| 2851 true_target(), | 2870 true_target(), |
| 2852 false_target(), | 2871 false_target(), |
| 2853 false); | 2872 false); |
| 2854 | 2873 |
| 2855 } else { | 2874 } else { |
| 2856 Label pop_and_continue, exit; | 2875 Label pop_and_continue, exit; |
| 2857 | 2876 |
| 2858 __ ldr(r0, MemOperand(sp, 0)); | 2877 __ ldr(r0, frame_->Top()); |
| 2859 __ push(r0); | 2878 __ push(r0); |
| 2860 // Avoid popping the result if it converts to 'true' using the | 2879 // Avoid popping the result if it converts to 'true' using the |
| 2861 // standard ToBoolean() conversion as described in ECMA-262, | 2880 // standard ToBoolean() conversion as described in ECMA-262, |
| 2862 // section 9.2, page 30. | 2881 // section 9.2, page 30. |
| 2863 ToBoolean(&exit, &pop_and_continue); | 2882 ToBoolean(&exit, &pop_and_continue); |
| 2864 Branch(true, &exit); | 2883 Branch(true, &exit); |
| 2865 | 2884 |
| 2866 // Pop the result of evaluating the first part. | 2885 // Pop the result of evaluating the first part. |
| 2867 __ bind(&pop_and_continue); | 2886 __ bind(&pop_and_continue); |
| 2868 __ pop(r0); | 2887 __ pop(r0); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2893 Load(node->left()); | 2912 Load(node->left()); |
| 2894 Load(node->right()); | 2913 Load(node->right()); |
| 2895 GenericBinaryOperation(node->op()); | 2914 GenericBinaryOperation(node->op()); |
| 2896 } | 2915 } |
| 2897 __ push(r0); | 2916 __ push(r0); |
| 2898 } | 2917 } |
| 2899 } | 2918 } |
| 2900 | 2919 |
| 2901 | 2920 |
| 2902 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 2921 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
| 2903 __ ldr(r0, FunctionOperand()); | 2922 __ ldr(r0, frame_->Function()); |
| 2904 __ push(r0); | 2923 __ push(r0); |
| 2905 } | 2924 } |
| 2906 | 2925 |
| 2907 | 2926 |
| 2908 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 2927 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
| 2909 Comment cmnt(masm_, "[ CompareOperation"); | 2928 Comment cmnt(masm_, "[ CompareOperation"); |
| 2910 | 2929 |
| 2911 // Get the expressions from the node. | 2930 // Get the expressions from the node. |
| 2912 Expression* left = node->left(); | 2931 Expression* left = node->left(); |
| 2913 Expression* right = node->right(); | 2932 Expression* right = node->right(); |
| (...skipping 1315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4229 // Slow-case: Non-function called. | 4248 // Slow-case: Non-function called. |
| 4230 __ bind(&slow); | 4249 __ bind(&slow); |
| 4231 __ mov(r0, Operand(argc_)); // Setup the number of arguments. | 4250 __ mov(r0, Operand(argc_)); // Setup the number of arguments. |
| 4232 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); | 4251 __ InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS); |
| 4233 } | 4252 } |
| 4234 | 4253 |
| 4235 | 4254 |
| 4236 #undef __ | 4255 #undef __ |
| 4237 | 4256 |
| 4238 } } // namespace v8::internal | 4257 } } // namespace v8::internal |
| OLD | NEW |