OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 24 matching lines...) Expand all Loading... |
35 // by the ABI to contain function return values. However, the first | 35 // by the ABI to contain function return values. However, the first |
36 // parameter to a function is defined to be 'a0'. So there are many | 36 // parameter to a function is defined to be 'a0'. So there are many |
37 // places where we have to move a previous result in v0 to a0 for the | 37 // places where we have to move a previous result in v0 to a0 for the |
38 // next call: mov(a0, v0). This is not needed on the other architectures. | 38 // next call: mov(a0, v0). This is not needed on the other architectures. |
39 | 39 |
40 #include "code-stubs.h" | 40 #include "code-stubs.h" |
41 #include "codegen.h" | 41 #include "codegen.h" |
42 #include "compiler.h" | 42 #include "compiler.h" |
43 #include "debug.h" | 43 #include "debug.h" |
44 #include "full-codegen.h" | 44 #include "full-codegen.h" |
| 45 #include "isolate-inl.h" |
45 #include "parser.h" | 46 #include "parser.h" |
46 #include "scopes.h" | 47 #include "scopes.h" |
47 #include "stub-cache.h" | 48 #include "stub-cache.h" |
48 | 49 |
49 #include "mips/code-stubs-mips.h" | 50 #include "mips/code-stubs-mips.h" |
50 #include "mips/macro-assembler-mips.h" | 51 #include "mips/macro-assembler-mips.h" |
51 | 52 |
52 namespace v8 { | 53 namespace v8 { |
53 namespace internal { | 54 namespace internal { |
54 | 55 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 | 113 |
113 private: | 114 private: |
114 MacroAssembler* masm_; | 115 MacroAssembler* masm_; |
115 Label patch_site_; | 116 Label patch_site_; |
116 #ifdef DEBUG | 117 #ifdef DEBUG |
117 bool info_emitted_; | 118 bool info_emitted_; |
118 #endif | 119 #endif |
119 }; | 120 }; |
120 | 121 |
121 | 122 |
| 123 // TODO(jkummerow): Obsolete as soon as x64 is updated. Remove. |
122 int FullCodeGenerator::self_optimization_header_size() { | 124 int FullCodeGenerator::self_optimization_header_size() { |
| 125 UNREACHABLE(); |
123 return 10 * Instruction::kInstrSize; | 126 return 10 * Instruction::kInstrSize; |
124 } | 127 } |
125 | 128 |
126 | 129 |
127 // Generate code for a JS function. On entry to the function the receiver | 130 // Generate code for a JS function. On entry to the function the receiver |
128 // and arguments have been pushed on the stack left to right. The actual | 131 // and arguments have been pushed on the stack left to right. The actual |
129 // argument count matches the formal parameter count expected by the | 132 // argument count matches the formal parameter count expected by the |
130 // function. | 133 // function. |
131 // | 134 // |
132 // The live registers are: | 135 // The live registers are: |
133 // o a1: the JS function object being called (i.e. ourselves) | 136 // o a1: the JS function object being called (i.e. ourselves) |
134 // o cp: our context | 137 // o cp: our context |
135 // o fp: our caller's frame pointer | 138 // o fp: our caller's frame pointer |
136 // o sp: stack pointer | 139 // o sp: stack pointer |
137 // o ra: return address | 140 // o ra: return address |
138 // | 141 // |
139 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 142 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
140 // frames-mips.h for its layout. | 143 // frames-mips.h for its layout. |
141 void FullCodeGenerator::Generate() { | 144 void FullCodeGenerator::Generate() { |
142 CompilationInfo* info = info_; | 145 CompilationInfo* info = info_; |
143 handler_table_ = | 146 handler_table_ = |
144 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 147 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); |
| 148 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( |
| 149 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget))); |
145 SetFunctionPosition(function()); | 150 SetFunctionPosition(function()); |
146 Comment cmnt(masm_, "[ function compiled by full code generator"); | 151 Comment cmnt(masm_, "[ function compiled by full code generator"); |
147 | 152 |
148 // We can optionally optimize based on counters rather than statistical | |
149 // sampling. | |
150 if (info->ShouldSelfOptimize()) { | |
151 if (FLAG_trace_opt_verbose) { | |
152 PrintF("[adding self-optimization header to %s]\n", | |
153 *info->function()->debug_name()->ToCString()); | |
154 } | |
155 has_self_optimization_header_ = true; | |
156 MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( | |
157 Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); | |
158 JSGlobalPropertyCell* cell; | |
159 if (maybe_cell->To(&cell)) { | |
160 __ li(a2, Handle<JSGlobalPropertyCell>(cell)); | |
161 __ lw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); | |
162 __ Subu(a3, a3, Operand(Smi::FromInt(1))); | |
163 __ sw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); | |
164 Handle<Code> compile_stub( | |
165 isolate()->builtins()->builtin(Builtins::kLazyRecompile)); | |
166 __ Jump(compile_stub, RelocInfo::CODE_TARGET, eq, a3, Operand(zero_reg)); | |
167 ASSERT_EQ(masm_->pc_offset(), self_optimization_header_size()); | |
168 } | |
169 } | |
170 | |
171 #ifdef DEBUG | 153 #ifdef DEBUG |
172 if (strlen(FLAG_stop_at) > 0 && | 154 if (strlen(FLAG_stop_at) > 0 && |
173 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 155 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
174 __ stop("stop-at"); | 156 __ stop("stop-at"); |
175 } | 157 } |
176 #endif | 158 #endif |
177 | 159 |
178 // Strict mode functions and builtins need to replace the receiver | 160 // Strict mode functions and builtins need to replace the receiver |
179 // with undefined when called as functions (without an explicit | 161 // with undefined when called as functions (without an explicit |
180 // receiver object). t1 is zero for method calls and non-zero for | 162 // receiver object). t1 is zero for method calls and non-zero for |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 EmitReturnSequence(); | 316 EmitReturnSequence(); |
335 } | 317 } |
336 | 318 |
337 | 319 |
338 void FullCodeGenerator::ClearAccumulator() { | 320 void FullCodeGenerator::ClearAccumulator() { |
339 ASSERT(Smi::FromInt(0) == 0); | 321 ASSERT(Smi::FromInt(0) == 0); |
340 __ mov(v0, zero_reg); | 322 __ mov(v0, zero_reg); |
341 } | 323 } |
342 | 324 |
343 | 325 |
| 326 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { |
| 327 __ li(a2, Operand(profiling_counter_)); |
| 328 __ lw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); |
| 329 __ Subu(a3, a3, Operand(Smi::FromInt(delta))); |
| 330 __ sw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); |
| 331 } |
| 332 |
| 333 |
| 334 void FullCodeGenerator::EmitProfilingCounterReset() { |
| 335 int reset_value = FLAG_interrupt_budget; |
| 336 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) { |
| 337 // Self-optimization is a one-off thing: if it fails, don't try again. |
| 338 reset_value = Smi::kMaxValue; |
| 339 } |
| 340 if (isolate()->IsDebuggerActive()) { |
| 341 // Detect debug break requests as soon as possible. |
| 342 reset_value = 10; |
| 343 } |
| 344 __ li(a2, Operand(profiling_counter_)); |
| 345 __ li(a3, Operand(Smi::FromInt(reset_value))); |
| 346 __ sw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset)); |
| 347 } |
| 348 |
| 349 |
| 350 static const int kMaxBackEdgeWeight = 127; |
| 351 static const int kBackEdgeDistanceDivisor = 142; |
| 352 |
| 353 |
344 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, | 354 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, |
345 Label* back_edge_target) { | 355 Label* back_edge_target) { |
346 // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need | 356 // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need |
347 // to make sure it is constant. Branch may emit a skip-or-jump sequence | 357 // to make sure it is constant. Branch may emit a skip-or-jump sequence |
348 // instead of the normal Branch. It seems that the "skip" part of that | 358 // instead of the normal Branch. It seems that the "skip" part of that |
349 // sequence is about as long as this Branch would be so it is safe to ignore | 359 // sequence is about as long as this Branch would be so it is safe to ignore |
350 // that. | 360 // that. |
351 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 361 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
352 Comment cmnt(masm_, "[ Stack check"); | 362 Comment cmnt(masm_, "[ Stack check"); |
353 Label ok; | 363 Label ok; |
354 __ LoadRoot(t0, Heap::kStackLimitRootIndex); | 364 if (FLAG_count_based_interrupts) { |
355 __ sltu(at, sp, t0); | 365 int weight = 1; |
356 __ beq(at, zero_reg, &ok); | 366 if (FLAG_weighted_back_edges) { |
357 // CallStub will emit a li t9, ... first, so it is safe to use the delay slot. | 367 ASSERT(back_edge_target->is_bound()); |
358 StackCheckStub stub; | 368 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
359 __ CallStub(&stub); | 369 weight = Min(kMaxBackEdgeWeight, |
| 370 Max(1, distance / kBackEdgeDistanceDivisor)); |
| 371 } |
| 372 EmitProfilingCounterDecrement(weight); |
| 373 __ slt(at, a3, zero_reg); |
| 374 __ beq(at, zero_reg, &ok); |
| 375 // CallStub will emit a li t9 first, so it is safe to use the delay slot. |
| 376 InterruptStub stub; |
| 377 __ CallStub(&stub); |
| 378 } else { |
| 379 __ LoadRoot(t0, Heap::kStackLimitRootIndex); |
| 380 __ sltu(at, sp, t0); |
| 381 __ beq(at, zero_reg, &ok); |
| 382 // CallStub will emit a li t9 first, so it is safe to use the delay slot. |
| 383 StackCheckStub stub; |
| 384 __ CallStub(&stub); |
| 385 } |
360 // Record a mapping of this PC offset to the OSR id. This is used to find | 386 // Record a mapping of this PC offset to the OSR id. This is used to find |
361 // the AST id from the unoptimized code in order to use it as a key into | 387 // the AST id from the unoptimized code in order to use it as a key into |
362 // the deoptimization input data found in the optimized code. | 388 // the deoptimization input data found in the optimized code. |
363 RecordStackCheck(stmt->OsrEntryId()); | 389 RecordStackCheck(stmt->OsrEntryId()); |
| 390 if (FLAG_count_based_interrupts) { |
| 391 EmitProfilingCounterReset(); |
| 392 } |
364 | 393 |
365 __ bind(&ok); | 394 __ bind(&ok); |
366 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 395 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
367 // Record a mapping of the OSR id to this PC. This is used if the OSR | 396 // Record a mapping of the OSR id to this PC. This is used if the OSR |
368 // entry becomes the target of a bailout. We don't expect it to be, but | 397 // entry becomes the target of a bailout. We don't expect it to be, but |
369 // we want it to work if it is. | 398 // we want it to work if it is. |
370 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); | 399 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); |
371 } | 400 } |
372 | 401 |
373 | 402 |
374 void FullCodeGenerator::EmitReturnSequence() { | 403 void FullCodeGenerator::EmitReturnSequence() { |
375 Comment cmnt(masm_, "[ Return sequence"); | 404 Comment cmnt(masm_, "[ Return sequence"); |
376 if (return_label_.is_bound()) { | 405 if (return_label_.is_bound()) { |
377 __ Branch(&return_label_); | 406 __ Branch(&return_label_); |
378 } else { | 407 } else { |
379 __ bind(&return_label_); | 408 __ bind(&return_label_); |
380 if (FLAG_trace) { | 409 if (FLAG_trace) { |
381 // Push the return value on the stack as the parameter. | 410 // Push the return value on the stack as the parameter. |
382 // Runtime::TraceExit returns its parameter in v0. | 411 // Runtime::TraceExit returns its parameter in v0. |
383 __ push(v0); | 412 __ push(v0); |
384 __ CallRuntime(Runtime::kTraceExit, 1); | 413 __ CallRuntime(Runtime::kTraceExit, 1); |
385 } | 414 } |
| 415 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { |
| 416 // Pretend that the exit is a backwards jump to the entry. |
| 417 int weight = 1; |
| 418 if (info_->ShouldSelfOptimize()) { |
| 419 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
| 420 } else if (FLAG_weighted_back_edges) { |
| 421 int distance = masm_->pc_offset(); |
| 422 weight = Min(kMaxBackEdgeWeight, |
| 423 Max(1, distance / kBackEdgeDistanceDivisor)); |
| 424 } |
| 425 EmitProfilingCounterDecrement(weight); |
| 426 Label ok; |
| 427 __ Branch(&ok, ge, a3, Operand(zero_reg)); |
| 428 __ push(v0); |
| 429 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { |
| 430 __ lw(a2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 431 __ push(a2); |
| 432 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); |
| 433 } else { |
| 434 InterruptStub stub; |
| 435 __ CallStub(&stub); |
| 436 } |
| 437 __ pop(v0); |
| 438 EmitProfilingCounterReset(); |
| 439 __ bind(&ok); |
| 440 } |
386 | 441 |
387 #ifdef DEBUG | 442 #ifdef DEBUG |
388 // Add a label for checking the size of the code used for returning. | 443 // Add a label for checking the size of the code used for returning. |
389 Label check_exit_codesize; | 444 Label check_exit_codesize; |
390 masm_->bind(&check_exit_codesize); | 445 masm_->bind(&check_exit_codesize); |
391 #endif | 446 #endif |
392 // Make sure that the constant pool is not emitted inside of the return | 447 // Make sure that the constant pool is not emitted inside of the return |
393 // sequence. | 448 // sequence. |
394 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 449 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
395 // Here we use masm_-> instead of the __ macro to avoid the code coverage | 450 // Here we use masm_-> instead of the __ macro to avoid the code coverage |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
895 __ Branch(&next_test, ne, a1, Operand(a0)); | 950 __ Branch(&next_test, ne, a1, Operand(a0)); |
896 __ Drop(1); // Switch value is no longer needed. | 951 __ Drop(1); // Switch value is no longer needed. |
897 __ Branch(clause->body_target()); | 952 __ Branch(clause->body_target()); |
898 | 953 |
899 __ bind(&slow_case); | 954 __ bind(&slow_case); |
900 } | 955 } |
901 | 956 |
902 // Record position before stub call for type feedback. | 957 // Record position before stub call for type feedback. |
903 SetSourcePosition(clause->position()); | 958 SetSourcePosition(clause->position()); |
904 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 959 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
905 __ Call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 960 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
906 patch_site.EmitPatchInfo(); | 961 patch_site.EmitPatchInfo(); |
907 | 962 |
908 __ Branch(&next_test, ne, v0, Operand(zero_reg)); | 963 __ Branch(&next_test, ne, v0, Operand(zero_reg)); |
909 __ Drop(1); // Switch value is no longer needed. | 964 __ Drop(1); // Switch value is no longer needed. |
910 __ Branch(clause->body_target()); | 965 __ Branch(clause->body_target()); |
911 } | 966 } |
912 | 967 |
913 // Discard the test value and jump to the default if present, otherwise to | 968 // Discard the test value and jump to the default if present, otherwise to |
914 // the end of the statement. | 969 // the end of the statement. |
915 __ bind(&next_test); | 970 __ bind(&next_test); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 __ Branch(&loop); | 1243 __ Branch(&loop); |
1189 __ bind(&fast); | 1244 __ bind(&fast); |
1190 } | 1245 } |
1191 | 1246 |
1192 __ lw(a0, GlobalObjectOperand()); | 1247 __ lw(a0, GlobalObjectOperand()); |
1193 __ li(a2, Operand(var->name())); | 1248 __ li(a2, Operand(var->name())); |
1194 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1249 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1195 ? RelocInfo::CODE_TARGET | 1250 ? RelocInfo::CODE_TARGET |
1196 : RelocInfo::CODE_TARGET_CONTEXT; | 1251 : RelocInfo::CODE_TARGET_CONTEXT; |
1197 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1252 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1198 __ Call(ic, mode); | 1253 CallIC(ic, mode); |
1199 } | 1254 } |
1200 | 1255 |
1201 | 1256 |
1202 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1257 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1203 Label* slow) { | 1258 Label* slow) { |
1204 ASSERT(var->IsContextSlot()); | 1259 ASSERT(var->IsContextSlot()); |
1205 Register context = cp; | 1260 Register context = cp; |
1206 Register next = a3; | 1261 Register next = a3; |
1207 Register temp = t0; | 1262 Register temp = t0; |
1208 | 1263 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 // Three cases: global variables, lookup variables, and all other types of | 1327 // Three cases: global variables, lookup variables, and all other types of |
1273 // variables. | 1328 // variables. |
1274 switch (var->location()) { | 1329 switch (var->location()) { |
1275 case Variable::UNALLOCATED: { | 1330 case Variable::UNALLOCATED: { |
1276 Comment cmnt(masm_, "Global variable"); | 1331 Comment cmnt(masm_, "Global variable"); |
1277 // Use inline caching. Variable name is passed in a2 and the global | 1332 // Use inline caching. Variable name is passed in a2 and the global |
1278 // object (receiver) in a0. | 1333 // object (receiver) in a0. |
1279 __ lw(a0, GlobalObjectOperand()); | 1334 __ lw(a0, GlobalObjectOperand()); |
1280 __ li(a2, Operand(var->name())); | 1335 __ li(a2, Operand(var->name())); |
1281 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1336 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1282 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1337 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1283 context()->Plug(v0); | 1338 context()->Plug(v0); |
1284 break; | 1339 break; |
1285 } | 1340 } |
1286 | 1341 |
1287 case Variable::PARAMETER: | 1342 case Variable::PARAMETER: |
1288 case Variable::LOCAL: | 1343 case Variable::LOCAL: |
1289 case Variable::CONTEXT: { | 1344 case Variable::CONTEXT: { |
1290 Comment cmnt(masm_, var->IsContextSlot() | 1345 Comment cmnt(masm_, var->IsContextSlot() |
1291 ? "Context variable" | 1346 ? "Context variable" |
1292 : "Stack variable"); | 1347 : "Stack variable"); |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1486 case ObjectLiteral::Property::COMPUTED: | 1541 case ObjectLiteral::Property::COMPUTED: |
1487 if (key->handle()->IsSymbol()) { | 1542 if (key->handle()->IsSymbol()) { |
1488 if (property->emit_store()) { | 1543 if (property->emit_store()) { |
1489 VisitForAccumulatorValue(value); | 1544 VisitForAccumulatorValue(value); |
1490 __ mov(a0, result_register()); | 1545 __ mov(a0, result_register()); |
1491 __ li(a2, Operand(key->handle())); | 1546 __ li(a2, Operand(key->handle())); |
1492 __ lw(a1, MemOperand(sp)); | 1547 __ lw(a1, MemOperand(sp)); |
1493 Handle<Code> ic = is_classic_mode() | 1548 Handle<Code> ic = is_classic_mode() |
1494 ? isolate()->builtins()->StoreIC_Initialize() | 1549 ? isolate()->builtins()->StoreIC_Initialize() |
1495 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1550 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1496 __ Call(ic, RelocInfo::CODE_TARGET, key->id()); | 1551 CallIC(ic, RelocInfo::CODE_TARGET, key->id()); |
1497 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1552 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1498 } else { | 1553 } else { |
1499 VisitForEffect(value); | 1554 VisitForEffect(value); |
1500 } | 1555 } |
1501 break; | 1556 break; |
1502 } | 1557 } |
1503 // Fall through. | 1558 // Fall through. |
1504 case ObjectLiteral::Property::PROTOTYPE: | 1559 case ObjectLiteral::Property::PROTOTYPE: |
1505 // Duplicate receiver on stack. | 1560 // Duplicate receiver on stack. |
1506 __ lw(a0, MemOperand(sp)); | 1561 __ lw(a0, MemOperand(sp)); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 } | 1814 } |
1760 | 1815 |
1761 | 1816 |
1762 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1817 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1763 SetSourcePosition(prop->position()); | 1818 SetSourcePosition(prop->position()); |
1764 Literal* key = prop->key()->AsLiteral(); | 1819 Literal* key = prop->key()->AsLiteral(); |
1765 __ mov(a0, result_register()); | 1820 __ mov(a0, result_register()); |
1766 __ li(a2, Operand(key->handle())); | 1821 __ li(a2, Operand(key->handle())); |
1767 // Call load IC. It has arguments receiver and property name a0 and a2. | 1822 // Call load IC. It has arguments receiver and property name a0 and a2. |
1768 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1823 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1769 __ Call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1824 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1770 } | 1825 } |
1771 | 1826 |
1772 | 1827 |
1773 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1828 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1774 SetSourcePosition(prop->position()); | 1829 SetSourcePosition(prop->position()); |
1775 __ mov(a0, result_register()); | 1830 __ mov(a0, result_register()); |
1776 // Call keyed load IC. It has arguments key and receiver in a0 and a1. | 1831 // Call keyed load IC. It has arguments key and receiver in a0 and a1. |
1777 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1832 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1778 __ Call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1833 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1779 } | 1834 } |
1780 | 1835 |
1781 | 1836 |
1782 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1837 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1783 Token::Value op, | 1838 Token::Value op, |
1784 OverwriteMode mode, | 1839 OverwriteMode mode, |
1785 Expression* left_expr, | 1840 Expression* left_expr, |
1786 Expression* right_expr) { | 1841 Expression* right_expr) { |
1787 Label done, smi_case, stub_call; | 1842 Label done, smi_case, stub_call; |
1788 | 1843 |
1789 Register scratch1 = a2; | 1844 Register scratch1 = a2; |
1790 Register scratch2 = a3; | 1845 Register scratch2 = a3; |
1791 | 1846 |
1792 // Get the arguments. | 1847 // Get the arguments. |
1793 Register left = a1; | 1848 Register left = a1; |
1794 Register right = a0; | 1849 Register right = a0; |
1795 __ pop(left); | 1850 __ pop(left); |
1796 __ mov(a0, result_register()); | 1851 __ mov(a0, result_register()); |
1797 | 1852 |
1798 // Perform combined smi check on both operands. | 1853 // Perform combined smi check on both operands. |
1799 __ Or(scratch1, left, Operand(right)); | 1854 __ Or(scratch1, left, Operand(right)); |
1800 STATIC_ASSERT(kSmiTag == 0); | 1855 STATIC_ASSERT(kSmiTag == 0); |
1801 JumpPatchSite patch_site(masm_); | 1856 JumpPatchSite patch_site(masm_); |
1802 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1857 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
1803 | 1858 |
1804 __ bind(&stub_call); | 1859 __ bind(&stub_call); |
1805 BinaryOpStub stub(op, mode); | 1860 BinaryOpStub stub(op, mode); |
1806 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1861 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1807 patch_site.EmitPatchInfo(); | 1862 patch_site.EmitPatchInfo(); |
1808 __ jmp(&done); | 1863 __ jmp(&done); |
1809 | 1864 |
1810 __ bind(&smi_case); | 1865 __ bind(&smi_case); |
1811 // Smi case. This code works the same way as the smi-smi case in the type | 1866 // Smi case. This code works the same way as the smi-smi case in the type |
1812 // recording binary operation stub, see | 1867 // recording binary operation stub, see |
1813 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 1868 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
1814 switch (op) { | 1869 switch (op) { |
1815 case Token::SAR: | 1870 case Token::SAR: |
1816 __ Branch(&stub_call); | 1871 __ Branch(&stub_call); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1879 } | 1934 } |
1880 | 1935 |
1881 | 1936 |
1882 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1937 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
1883 Token::Value op, | 1938 Token::Value op, |
1884 OverwriteMode mode) { | 1939 OverwriteMode mode) { |
1885 __ mov(a0, result_register()); | 1940 __ mov(a0, result_register()); |
1886 __ pop(a1); | 1941 __ pop(a1); |
1887 BinaryOpStub stub(op, mode); | 1942 BinaryOpStub stub(op, mode); |
1888 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1943 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
1889 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1944 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1890 patch_site.EmitPatchInfo(); | 1945 patch_site.EmitPatchInfo(); |
1891 context()->Plug(v0); | 1946 context()->Plug(v0); |
1892 } | 1947 } |
1893 | 1948 |
1894 | 1949 |
1895 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1950 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1896 // Invalid left-hand sides are rewritten to have a 'throw | 1951 // Invalid left-hand sides are rewritten to have a 'throw |
1897 // ReferenceError' on the left-hand side. | 1952 // ReferenceError' on the left-hand side. |
1898 if (!expr->IsValidLeftHandSide()) { | 1953 if (!expr->IsValidLeftHandSide()) { |
1899 VisitForEffect(expr); | 1954 VisitForEffect(expr); |
(...skipping 20 matching lines...) Expand all Loading... |
1920 } | 1975 } |
1921 case NAMED_PROPERTY: { | 1976 case NAMED_PROPERTY: { |
1922 __ push(result_register()); // Preserve value. | 1977 __ push(result_register()); // Preserve value. |
1923 VisitForAccumulatorValue(prop->obj()); | 1978 VisitForAccumulatorValue(prop->obj()); |
1924 __ mov(a1, result_register()); | 1979 __ mov(a1, result_register()); |
1925 __ pop(a0); // Restore value. | 1980 __ pop(a0); // Restore value. |
1926 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); | 1981 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); |
1927 Handle<Code> ic = is_classic_mode() | 1982 Handle<Code> ic = is_classic_mode() |
1928 ? isolate()->builtins()->StoreIC_Initialize() | 1983 ? isolate()->builtins()->StoreIC_Initialize() |
1929 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1984 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1930 __ Call(ic); | 1985 CallIC(ic); |
1931 break; | 1986 break; |
1932 } | 1987 } |
1933 case KEYED_PROPERTY: { | 1988 case KEYED_PROPERTY: { |
1934 __ push(result_register()); // Preserve value. | 1989 __ push(result_register()); // Preserve value. |
1935 VisitForStackValue(prop->obj()); | 1990 VisitForStackValue(prop->obj()); |
1936 VisitForAccumulatorValue(prop->key()); | 1991 VisitForAccumulatorValue(prop->key()); |
1937 __ mov(a1, result_register()); | 1992 __ mov(a1, result_register()); |
1938 __ pop(a2); | 1993 __ pop(a2); |
1939 __ pop(a0); // Restore value. | 1994 __ pop(a0); // Restore value. |
1940 Handle<Code> ic = is_classic_mode() | 1995 Handle<Code> ic = is_classic_mode() |
1941 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 1996 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1942 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 1997 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1943 __ Call(ic); | 1998 CallIC(ic); |
1944 break; | 1999 break; |
1945 } | 2000 } |
1946 } | 2001 } |
1947 context()->Plug(v0); | 2002 context()->Plug(v0); |
1948 } | 2003 } |
1949 | 2004 |
1950 | 2005 |
1951 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2006 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1952 Token::Value op) { | 2007 Token::Value op) { |
1953 if (var->IsUnallocated()) { | 2008 if (var->IsUnallocated()) { |
1954 // Global var, const, or let. | 2009 // Global var, const, or let. |
1955 __ mov(a0, result_register()); | 2010 __ mov(a0, result_register()); |
1956 __ li(a2, Operand(var->name())); | 2011 __ li(a2, Operand(var->name())); |
1957 __ lw(a1, GlobalObjectOperand()); | 2012 __ lw(a1, GlobalObjectOperand()); |
1958 Handle<Code> ic = is_classic_mode() | 2013 Handle<Code> ic = is_classic_mode() |
1959 ? isolate()->builtins()->StoreIC_Initialize() | 2014 ? isolate()->builtins()->StoreIC_Initialize() |
1960 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2015 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1961 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 2016 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1962 | 2017 |
1963 } else if (op == Token::INIT_CONST) { | 2018 } else if (op == Token::INIT_CONST) { |
1964 // Const initializers need a write barrier. | 2019 // Const initializers need a write barrier. |
1965 ASSERT(!var->IsParameter()); // No const parameters. | 2020 ASSERT(!var->IsParameter()); // No const parameters. |
1966 if (var->IsStackLocal()) { | 2021 if (var->IsStackLocal()) { |
1967 Label skip; | 2022 Label skip; |
1968 __ lw(a1, StackOperand(var)); | 2023 __ lw(a1, StackOperand(var)); |
1969 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2024 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
1970 __ Branch(&skip, ne, a1, Operand(t0)); | 2025 __ Branch(&skip, ne, a1, Operand(t0)); |
1971 __ sw(result_register(), StackOperand(var)); | 2026 __ sw(result_register(), StackOperand(var)); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2070 // receiver into fast case. | 2125 // receiver into fast case. |
2071 if (expr->ends_initialization_block()) { | 2126 if (expr->ends_initialization_block()) { |
2072 __ lw(a1, MemOperand(sp)); | 2127 __ lw(a1, MemOperand(sp)); |
2073 } else { | 2128 } else { |
2074 __ pop(a1); | 2129 __ pop(a1); |
2075 } | 2130 } |
2076 | 2131 |
2077 Handle<Code> ic = is_classic_mode() | 2132 Handle<Code> ic = is_classic_mode() |
2078 ? isolate()->builtins()->StoreIC_Initialize() | 2133 ? isolate()->builtins()->StoreIC_Initialize() |
2079 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2134 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2080 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2135 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2081 | 2136 |
2082 // If the assignment ends an initialization block, revert to fast case. | 2137 // If the assignment ends an initialization block, revert to fast case. |
2083 if (expr->ends_initialization_block()) { | 2138 if (expr->ends_initialization_block()) { |
2084 __ push(v0); // Result of assignment, saved even if not needed. | 2139 __ push(v0); // Result of assignment, saved even if not needed. |
2085 // Receiver is under the result value. | 2140 // Receiver is under the result value. |
2086 __ lw(t0, MemOperand(sp, kPointerSize)); | 2141 __ lw(t0, MemOperand(sp, kPointerSize)); |
2087 __ push(t0); | 2142 __ push(t0); |
2088 __ CallRuntime(Runtime::kToFastProperties, 1); | 2143 __ CallRuntime(Runtime::kToFastProperties, 1); |
2089 __ pop(v0); | 2144 __ pop(v0); |
2090 __ Drop(1); | 2145 __ Drop(1); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 // receiver into fast case. | 2177 // receiver into fast case. |
2123 if (expr->ends_initialization_block()) { | 2178 if (expr->ends_initialization_block()) { |
2124 __ lw(a2, MemOperand(sp)); | 2179 __ lw(a2, MemOperand(sp)); |
2125 } else { | 2180 } else { |
2126 __ pop(a2); | 2181 __ pop(a2); |
2127 } | 2182 } |
2128 | 2183 |
2129 Handle<Code> ic = is_classic_mode() | 2184 Handle<Code> ic = is_classic_mode() |
2130 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2185 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2131 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2186 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2132 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2187 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2133 | 2188 |
2134 // If the assignment ends an initialization block, revert to fast case. | 2189 // If the assignment ends an initialization block, revert to fast case. |
2135 if (expr->ends_initialization_block()) { | 2190 if (expr->ends_initialization_block()) { |
2136 __ push(v0); // Result of assignment, saved even if not needed. | 2191 __ push(v0); // Result of assignment, saved even if not needed. |
2137 // Receiver is under the result value. | 2192 // Receiver is under the result value. |
2138 __ lw(t0, MemOperand(sp, kPointerSize)); | 2193 __ lw(t0, MemOperand(sp, kPointerSize)); |
2139 __ push(t0); | 2194 __ push(t0); |
2140 __ CallRuntime(Runtime::kToFastProperties, 1); | 2195 __ CallRuntime(Runtime::kToFastProperties, 1); |
2141 __ pop(v0); | 2196 __ pop(v0); |
2142 __ Drop(1); | 2197 __ Drop(1); |
(...skipping 14 matching lines...) Expand all Loading... |
2157 } else { | 2212 } else { |
2158 VisitForStackValue(expr->obj()); | 2213 VisitForStackValue(expr->obj()); |
2159 VisitForAccumulatorValue(expr->key()); | 2214 VisitForAccumulatorValue(expr->key()); |
2160 __ pop(a1); | 2215 __ pop(a1); |
2161 EmitKeyedPropertyLoad(expr); | 2216 EmitKeyedPropertyLoad(expr); |
2162 context()->Plug(v0); | 2217 context()->Plug(v0); |
2163 } | 2218 } |
2164 } | 2219 } |
2165 | 2220 |
2166 | 2221 |
| 2222 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2223 RelocInfo::Mode rmode, |
| 2224 unsigned ast_id) { |
| 2225 ic_total_count_++; |
| 2226 __ Call(code, rmode, ast_id); |
| 2227 } |
| 2228 |
| 2229 |
2167 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2230 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
2168 Handle<Object> name, | 2231 Handle<Object> name, |
2169 RelocInfo::Mode mode) { | 2232 RelocInfo::Mode mode) { |
2170 // Code common for calls using the IC. | 2233 // Code common for calls using the IC. |
2171 ZoneList<Expression*>* args = expr->arguments(); | 2234 ZoneList<Expression*>* args = expr->arguments(); |
2172 int arg_count = args->length(); | 2235 int arg_count = args->length(); |
2173 { PreservePositionScope scope(masm()->positions_recorder()); | 2236 { PreservePositionScope scope(masm()->positions_recorder()); |
2174 for (int i = 0; i < arg_count; i++) { | 2237 for (int i = 0; i < arg_count; i++) { |
2175 VisitForStackValue(args->at(i)); | 2238 VisitForStackValue(args->at(i)); |
2176 } | 2239 } |
2177 __ li(a2, Operand(name)); | 2240 __ li(a2, Operand(name)); |
2178 } | 2241 } |
2179 // Record source position for debugger. | 2242 // Record source position for debugger. |
2180 SetSourcePosition(expr->position()); | 2243 SetSourcePosition(expr->position()); |
2181 // Call the IC initialization code. | 2244 // Call the IC initialization code. |
2182 Handle<Code> ic = | 2245 Handle<Code> ic = |
2183 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2246 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
2184 __ Call(ic, mode, expr->id()); | 2247 CallIC(ic, mode, expr->id()); |
2185 RecordJSReturnSite(expr); | 2248 RecordJSReturnSite(expr); |
2186 // Restore context register. | 2249 // Restore context register. |
2187 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2250 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2188 context()->Plug(v0); | 2251 context()->Plug(v0); |
2189 } | 2252 } |
2190 | 2253 |
2191 | 2254 |
2192 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2255 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2193 Expression* key) { | 2256 Expression* key) { |
2194 // Load the key. | 2257 // Load the key. |
(...skipping 12 matching lines...) Expand all Loading... |
2207 for (int i = 0; i < arg_count; i++) { | 2270 for (int i = 0; i < arg_count; i++) { |
2208 VisitForStackValue(args->at(i)); | 2271 VisitForStackValue(args->at(i)); |
2209 } | 2272 } |
2210 } | 2273 } |
2211 // Record source position for debugger. | 2274 // Record source position for debugger. |
2212 SetSourcePosition(expr->position()); | 2275 SetSourcePosition(expr->position()); |
2213 // Call the IC initialization code. | 2276 // Call the IC initialization code. |
2214 Handle<Code> ic = | 2277 Handle<Code> ic = |
2215 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2278 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
2216 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2279 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2217 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2280 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2218 RecordJSReturnSite(expr); | 2281 RecordJSReturnSite(expr); |
2219 // Restore context register. | 2282 // Restore context register. |
2220 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2283 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2221 context()->DropAndPlug(1, v0); // Drop the key still on the stack. | 2284 context()->DropAndPlug(1, v0); // Drop the key still on the stack. |
2222 } | 2285 } |
2223 | 2286 |
2224 | 2287 |
2225 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2288 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2226 // Code common for calls using the call stub. | 2289 // Code common for calls using the call stub. |
2227 ZoneList<Expression*>* args = expr->arguments(); | 2290 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 1593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3821 for (int i = 0; i < arg_count; i++) { | 3884 for (int i = 0; i < arg_count; i++) { |
3822 VisitForStackValue(args->at(i)); | 3885 VisitForStackValue(args->at(i)); |
3823 } | 3886 } |
3824 | 3887 |
3825 if (expr->is_jsruntime()) { | 3888 if (expr->is_jsruntime()) { |
3826 // Call the JS runtime function. | 3889 // Call the JS runtime function. |
3827 __ li(a2, Operand(expr->name())); | 3890 __ li(a2, Operand(expr->name())); |
3828 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3891 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3829 Handle<Code> ic = | 3892 Handle<Code> ic = |
3830 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 3893 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
3831 __ Call(ic, mode, expr->id()); | 3894 CallIC(ic, mode, expr->id()); |
3832 // Restore context register. | 3895 // Restore context register. |
3833 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3896 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3834 } else { | 3897 } else { |
3835 // Call the C runtime function. | 3898 // Call the C runtime function. |
3836 __ CallRuntime(expr->function(), arg_count); | 3899 __ CallRuntime(expr->function(), arg_count); |
3837 } | 3900 } |
3838 context()->Plug(v0); | 3901 context()->Plug(v0); |
3839 } | 3902 } |
3840 | 3903 |
3841 | 3904 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3977 // TODO(svenpanne): Allowing format strings in Comment would be nice here... | 4040 // TODO(svenpanne): Allowing format strings in Comment would be nice here... |
3978 Comment cmt(masm_, comment); | 4041 Comment cmt(masm_, comment); |
3979 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); | 4042 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
3980 UnaryOverwriteMode overwrite = | 4043 UnaryOverwriteMode overwrite = |
3981 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 4044 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
3982 UnaryOpStub stub(expr->op(), overwrite); | 4045 UnaryOpStub stub(expr->op(), overwrite); |
3983 // GenericUnaryOpStub expects the argument to be in a0. | 4046 // GenericUnaryOpStub expects the argument to be in a0. |
3984 VisitForAccumulatorValue(expr->expression()); | 4047 VisitForAccumulatorValue(expr->expression()); |
3985 SetSourcePosition(expr->position()); | 4048 SetSourcePosition(expr->position()); |
3986 __ mov(a0, result_register()); | 4049 __ mov(a0, result_register()); |
3987 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 4050 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
3988 context()->Plug(v0); | 4051 context()->Plug(v0); |
3989 } | 4052 } |
3990 | 4053 |
3991 | 4054 |
3992 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4055 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
3993 Comment cmnt(masm_, "[ CountOperation"); | 4056 Comment cmnt(masm_, "[ CountOperation"); |
3994 SetSourcePosition(expr->position()); | 4057 SetSourcePosition(expr->position()); |
3995 | 4058 |
3996 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 4059 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
3997 // as the left-hand side. | 4060 // as the left-hand side. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4088 // We could eliminate this smi check if we split the code at | 4151 // We could eliminate this smi check if we split the code at |
4089 // the first smi check before calling ToNumber. | 4152 // the first smi check before calling ToNumber. |
4090 patch_site.EmitJumpIfSmi(v0, &done); | 4153 patch_site.EmitJumpIfSmi(v0, &done); |
4091 __ bind(&stub_call); | 4154 __ bind(&stub_call); |
4092 } | 4155 } |
4093 | 4156 |
4094 // Record position before stub call. | 4157 // Record position before stub call. |
4095 SetSourcePosition(expr->position()); | 4158 SetSourcePosition(expr->position()); |
4096 | 4159 |
4097 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 4160 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
4098 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); | 4161 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
4099 patch_site.EmitPatchInfo(); | 4162 patch_site.EmitPatchInfo(); |
4100 __ bind(&done); | 4163 __ bind(&done); |
4101 | 4164 |
4102 // Store the value returned in v0. | 4165 // Store the value returned in v0. |
4103 switch (assign_type) { | 4166 switch (assign_type) { |
4104 case VARIABLE: | 4167 case VARIABLE: |
4105 if (expr->is_postfix()) { | 4168 if (expr->is_postfix()) { |
4106 { EffectContext context(this); | 4169 { EffectContext context(this); |
4107 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4170 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
4108 Token::ASSIGN); | 4171 Token::ASSIGN); |
(...skipping 12 matching lines...) Expand all Loading... |
4121 context()->Plug(v0); | 4184 context()->Plug(v0); |
4122 } | 4185 } |
4123 break; | 4186 break; |
4124 case NAMED_PROPERTY: { | 4187 case NAMED_PROPERTY: { |
4125 __ mov(a0, result_register()); // Value. | 4188 __ mov(a0, result_register()); // Value. |
4126 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); // Name. | 4189 __ li(a2, Operand(prop->key()->AsLiteral()->handle())); // Name. |
4127 __ pop(a1); // Receiver. | 4190 __ pop(a1); // Receiver. |
4128 Handle<Code> ic = is_classic_mode() | 4191 Handle<Code> ic = is_classic_mode() |
4129 ? isolate()->builtins()->StoreIC_Initialize() | 4192 ? isolate()->builtins()->StoreIC_Initialize() |
4130 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 4193 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
4131 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4194 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4132 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4195 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4133 if (expr->is_postfix()) { | 4196 if (expr->is_postfix()) { |
4134 if (!context()->IsEffect()) { | 4197 if (!context()->IsEffect()) { |
4135 context()->PlugTOS(); | 4198 context()->PlugTOS(); |
4136 } | 4199 } |
4137 } else { | 4200 } else { |
4138 context()->Plug(v0); | 4201 context()->Plug(v0); |
4139 } | 4202 } |
4140 break; | 4203 break; |
4141 } | 4204 } |
4142 case KEYED_PROPERTY: { | 4205 case KEYED_PROPERTY: { |
4143 __ mov(a0, result_register()); // Value. | 4206 __ mov(a0, result_register()); // Value. |
4144 __ pop(a1); // Key. | 4207 __ pop(a1); // Key. |
4145 __ pop(a2); // Receiver. | 4208 __ pop(a2); // Receiver. |
4146 Handle<Code> ic = is_classic_mode() | 4209 Handle<Code> ic = is_classic_mode() |
4147 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4210 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4148 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4211 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4149 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4212 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4150 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4213 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4151 if (expr->is_postfix()) { | 4214 if (expr->is_postfix()) { |
4152 if (!context()->IsEffect()) { | 4215 if (!context()->IsEffect()) { |
4153 context()->PlugTOS(); | 4216 context()->PlugTOS(); |
4154 } | 4217 } |
4155 } else { | 4218 } else { |
4156 context()->Plug(v0); | 4219 context()->Plug(v0); |
4157 } | 4220 } |
4158 break; | 4221 break; |
4159 } | 4222 } |
4160 } | 4223 } |
4161 } | 4224 } |
4162 | 4225 |
4163 | 4226 |
4164 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4227 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4165 ASSERT(!context()->IsEffect()); | 4228 ASSERT(!context()->IsEffect()); |
4166 ASSERT(!context()->IsTest()); | 4229 ASSERT(!context()->IsTest()); |
4167 VariableProxy* proxy = expr->AsVariableProxy(); | 4230 VariableProxy* proxy = expr->AsVariableProxy(); |
4168 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4231 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4169 Comment cmnt(masm_, "Global variable"); | 4232 Comment cmnt(masm_, "Global variable"); |
4170 __ lw(a0, GlobalObjectOperand()); | 4233 __ lw(a0, GlobalObjectOperand()); |
4171 __ li(a2, Operand(proxy->name())); | 4234 __ li(a2, Operand(proxy->name())); |
4172 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 4235 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
4173 // Use a regular load, not a contextual load, to avoid a reference | 4236 // Use a regular load, not a contextual load, to avoid a reference |
4174 // error. | 4237 // error. |
4175 __ Call(ic); | 4238 CallIC(ic); |
4176 PrepareForBailout(expr, TOS_REG); | 4239 PrepareForBailout(expr, TOS_REG); |
4177 context()->Plug(v0); | 4240 context()->Plug(v0); |
4178 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4241 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
4179 Label done, slow; | 4242 Label done, slow; |
4180 | 4243 |
4181 // Generate code for loading from variables potentially shadowed | 4244 // Generate code for loading from variables potentially shadowed |
4182 // by eval-introduced variables. | 4245 // by eval-introduced variables. |
4183 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4246 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
4184 | 4247 |
4185 __ bind(&slow); | 4248 __ bind(&slow); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4343 if (inline_smi_code) { | 4406 if (inline_smi_code) { |
4344 Label slow_case; | 4407 Label slow_case; |
4345 __ Or(a2, a0, Operand(a1)); | 4408 __ Or(a2, a0, Operand(a1)); |
4346 patch_site.EmitJumpIfNotSmi(a2, &slow_case); | 4409 patch_site.EmitJumpIfNotSmi(a2, &slow_case); |
4347 Split(cc, a1, Operand(a0), if_true, if_false, NULL); | 4410 Split(cc, a1, Operand(a0), if_true, if_false, NULL); |
4348 __ bind(&slow_case); | 4411 __ bind(&slow_case); |
4349 } | 4412 } |
4350 // Record position and call the compare IC. | 4413 // Record position and call the compare IC. |
4351 SetSourcePosition(expr->position()); | 4414 SetSourcePosition(expr->position()); |
4352 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4415 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4353 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4416 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4354 patch_site.EmitPatchInfo(); | 4417 patch_site.EmitPatchInfo(); |
4355 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4418 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4356 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); | 4419 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); |
4357 } | 4420 } |
4358 } | 4421 } |
4359 | 4422 |
4360 // Convert the result of the comparison into one expected for this | 4423 // Convert the result of the comparison into one expected for this |
4361 // expression's context. | 4424 // expression's context. |
4362 context()->Plug(if_true, if_false); | 4425 context()->Plug(if_true, if_false); |
4363 } | 4426 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4503 *context_length = 0; | 4566 *context_length = 0; |
4504 return previous_; | 4567 return previous_; |
4505 } | 4568 } |
4506 | 4569 |
4507 | 4570 |
4508 #undef __ | 4571 #undef __ |
4509 | 4572 |
4510 } } // namespace v8::internal | 4573 } } // namespace v8::internal |
4511 | 4574 |
4512 #endif // V8_TARGET_ARCH_MIPS | 4575 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |