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 16 matching lines...) Expand all Loading... | |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if defined(V8_TARGET_ARCH_ARM) | 30 #if defined(V8_TARGET_ARCH_ARM) |
31 | 31 |
32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
33 #include "codegen.h" | 33 #include "codegen.h" |
34 #include "compiler.h" | 34 #include "compiler.h" |
35 #include "debug.h" | 35 #include "debug.h" |
36 #include "full-codegen.h" | 36 #include "full-codegen.h" |
37 #include "isolate-inl.h" | |
37 #include "parser.h" | 38 #include "parser.h" |
38 #include "scopes.h" | 39 #include "scopes.h" |
39 #include "stub-cache.h" | 40 #include "stub-cache.h" |
40 | 41 |
41 #include "arm/code-stubs-arm.h" | 42 #include "arm/code-stubs-arm.h" |
42 #include "arm/macro-assembler-arm.h" | 43 #include "arm/macro-assembler-arm.h" |
43 | 44 |
44 namespace v8 { | 45 namespace v8 { |
45 namespace internal { | 46 namespace internal { |
46 | 47 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 | 103 |
103 private: | 104 private: |
104 MacroAssembler* masm_; | 105 MacroAssembler* masm_; |
105 Label patch_site_; | 106 Label patch_site_; |
106 #ifdef DEBUG | 107 #ifdef DEBUG |
107 bool info_emitted_; | 108 bool info_emitted_; |
108 #endif | 109 #endif |
109 }; | 110 }; |
110 | 111 |
111 | 112 |
113 // TODO(jkummerow): Obsolete as soon as x64 is updated. Remove. | |
Erik Corry
2012/03/23 09:55:53
Does this really have to do with x64?
Jakob Kummerow
2012/03/23 12:07:32
Yes. I don't want to break compilation before thes
| |
112 int FullCodeGenerator::self_optimization_header_size() { | 114 int FullCodeGenerator::self_optimization_header_size() { |
115 UNREACHABLE(); | |
113 return 24; | 116 return 24; |
114 } | 117 } |
115 | 118 |
116 | 119 |
117 // Generate code for a JS function. On entry to the function the receiver | 120 // Generate code for a JS function. On entry to the function the receiver |
118 // and arguments have been pushed on the stack left to right. The actual | 121 // and arguments have been pushed on the stack left to right. The actual |
119 // argument count matches the formal parameter count expected by the | 122 // argument count matches the formal parameter count expected by the |
120 // function. | 123 // function. |
121 // | 124 // |
122 // The live registers are: | 125 // The live registers are: |
123 // o r1: the JS function object being called (i.e., ourselves) | 126 // o r1: the JS function object being called (i.e., ourselves) |
124 // o cp: our context | 127 // o cp: our context |
125 // o fp: our caller's frame pointer | 128 // o fp: our caller's frame pointer |
126 // o sp: stack pointer | 129 // o sp: stack pointer |
127 // o lr: return address | 130 // o lr: return address |
128 // | 131 // |
129 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 132 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
130 // frames-arm.h for its layout. | 133 // frames-arm.h for its layout. |
131 void FullCodeGenerator::Generate() { | 134 void FullCodeGenerator::Generate() { |
132 CompilationInfo* info = info_; | 135 CompilationInfo* info = info_; |
133 handler_table_ = | 136 handler_table_ = |
134 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 137 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); |
138 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( | |
139 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget))); | |
135 SetFunctionPosition(function()); | 140 SetFunctionPosition(function()); |
136 Comment cmnt(masm_, "[ function compiled by full code generator"); | 141 Comment cmnt(masm_, "[ function compiled by full code generator"); |
137 | 142 |
138 // We can optionally optimize based on counters rather than statistical | |
139 // sampling. | |
140 if (info->ShouldSelfOptimize()) { | |
141 if (FLAG_trace_opt_verbose) { | |
142 PrintF("[adding self-optimization header to %s]\n", | |
143 *info->function()->debug_name()->ToCString()); | |
144 } | |
145 has_self_optimization_header_ = true; | |
146 MaybeObject* maybe_cell = isolate()->heap()->AllocateJSGlobalPropertyCell( | |
147 Smi::FromInt(Compiler::kCallsUntilPrimitiveOpt)); | |
148 JSGlobalPropertyCell* cell; | |
149 if (maybe_cell->To(&cell)) { | |
150 __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell))); | |
151 __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | |
152 __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC); | |
153 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | |
154 Handle<Code> compile_stub( | |
155 isolate()->builtins()->builtin(Builtins::kLazyRecompile)); | |
156 __ Jump(compile_stub, RelocInfo::CODE_TARGET, eq); | |
157 ASSERT(masm_->pc_offset() == self_optimization_header_size()); | |
158 } | |
159 } | |
160 | |
161 #ifdef DEBUG | 143 #ifdef DEBUG |
162 if (strlen(FLAG_stop_at) > 0 && | 144 if (strlen(FLAG_stop_at) > 0 && |
163 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { | 145 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { |
164 __ stop("stop-at"); | 146 __ stop("stop-at"); |
165 } | 147 } |
166 #endif | 148 #endif |
167 | 149 |
168 // Strict mode functions and builtins need to replace the receiver | 150 // Strict mode functions and builtins need to replace the receiver |
169 // with undefined when called as functions (without an explicit | 151 // with undefined when called as functions (without an explicit |
170 // receiver object). r5 is zero for method calls and non-zero for | 152 // receiver object). r5 is zero for method calls and non-zero for |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 // of the stack check table. | 311 // of the stack check table. |
330 masm()->CheckConstPool(true, false); | 312 masm()->CheckConstPool(true, false); |
331 } | 313 } |
332 | 314 |
333 | 315 |
334 void FullCodeGenerator::ClearAccumulator() { | 316 void FullCodeGenerator::ClearAccumulator() { |
335 __ mov(r0, Operand(Smi::FromInt(0))); | 317 __ mov(r0, Operand(Smi::FromInt(0))); |
336 } | 318 } |
337 | 319 |
338 | 320 |
321 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { | |
322 __ mov(r2, Operand(profiling_counter_)); | |
323 __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | |
324 __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC); | |
325 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | |
326 } | |
327 | |
328 | |
329 void FullCodeGenerator::EmitProfilingCounterReset() { | |
330 int reset_value = FLAG_interrupt_budget; | |
331 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) { | |
332 // Self-optimization is a one-off thing: if it fails, don't try again. | |
333 reset_value = Smi::kMaxValue; | |
334 } | |
335 if (isolate()->IsDebuggerActive()) { | |
336 reset_value = 10; | |
337 } | |
338 __ mov(r2, Operand(profiling_counter_)); | |
339 __ mov(r3, Operand(Smi::FromInt(reset_value))); | |
340 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | |
341 } | |
342 | |
343 | |
339 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, | 344 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, |
340 Label* back_edge_target) { | 345 Label* back_edge_target) { |
341 Comment cmnt(masm_, "[ Stack check"); | 346 Comment cmnt(masm_, "[ Stack check"); |
342 Label ok; | 347 Label ok; |
343 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 348 |
344 __ cmp(sp, Operand(ip)); | 349 if (FLAG_count_based_interrupts) { |
345 __ b(hs, &ok); | 350 int weight = 1; |
346 StackCheckStub stub; | 351 if (FLAG_weighted_back_edges) { |
347 __ CallStub(&stub); | 352 ASSERT(back_edge_target->is_bound()); |
353 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); | |
354 weight = Min(127, Max(1, distance / 142)); | |
Erik Corry
2012/03/23 09:55:53
These constants need names.
Jakob Kummerow
2012/03/23 12:07:32
Done.
| |
355 } | |
356 EmitProfilingCounterDecrement(weight); | |
357 __ b(pl, &ok); | |
358 InterruptStub stub; | |
359 __ CallStub(&stub); | |
360 } else { | |
361 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | |
362 __ cmp(sp, Operand(ip)); | |
363 __ b(hs, &ok); | |
364 StackCheckStub stub; | |
365 __ CallStub(&stub); | |
366 } | |
367 | |
348 // Record a mapping of this PC offset to the OSR id. This is used to find | 368 // Record a mapping of this PC offset to the OSR id. This is used to find |
349 // the AST id from the unoptimized code in order to use it as a key into | 369 // the AST id from the unoptimized code in order to use it as a key into |
350 // the deoptimization input data found in the optimized code. | 370 // the deoptimization input data found in the optimized code. |
351 RecordStackCheck(stmt->OsrEntryId()); | 371 RecordStackCheck(stmt->OsrEntryId()); |
352 | 372 |
373 if (FLAG_count_based_interrupts) { | |
374 EmitProfilingCounterReset(); | |
375 } | |
376 | |
353 __ bind(&ok); | 377 __ bind(&ok); |
354 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 378 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
355 // Record a mapping of the OSR id to this PC. This is used if the OSR | 379 // Record a mapping of the OSR id to this PC. This is used if the OSR |
356 // entry becomes the target of a bailout. We don't expect it to be, but | 380 // entry becomes the target of a bailout. We don't expect it to be, but |
357 // we want it to work if it is. | 381 // we want it to work if it is. |
358 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); | 382 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); |
359 } | 383 } |
360 | 384 |
361 | 385 |
362 void FullCodeGenerator::EmitReturnSequence() { | 386 void FullCodeGenerator::EmitReturnSequence() { |
363 Comment cmnt(masm_, "[ Return sequence"); | 387 Comment cmnt(masm_, "[ Return sequence"); |
364 if (return_label_.is_bound()) { | 388 if (return_label_.is_bound()) { |
365 __ b(&return_label_); | 389 __ b(&return_label_); |
366 } else { | 390 } else { |
367 __ bind(&return_label_); | 391 __ bind(&return_label_); |
368 if (FLAG_trace) { | 392 if (FLAG_trace) { |
369 // Push the return value on the stack as the parameter. | 393 // Push the return value on the stack as the parameter. |
370 // Runtime::TraceExit returns its parameter in r0. | 394 // Runtime::TraceExit returns its parameter in r0. |
371 __ push(r0); | 395 __ push(r0); |
372 __ CallRuntime(Runtime::kTraceExit, 1); | 396 __ CallRuntime(Runtime::kTraceExit, 1); |
373 } | 397 } |
398 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { | |
399 // Pretend that the exit is a backwards jump to the entry. | |
400 int weight = 1; | |
401 if (info_->ShouldSelfOptimize()) { | |
402 weight = FLAG_interrupt_budget / FLAG_self_opt_count; | |
403 } else if (FLAG_weighted_back_edges) { | |
404 int distance = masm_->pc_offset(); | |
405 weight = Min(127, Max(1, distance / 142)); | |
Erik Corry
2012/03/23 09:55:53
Here they are again! (Or are these new constants
Jakob Kummerow
2012/03/23 12:07:32
Done.
| |
406 } | |
407 EmitProfilingCounterDecrement(weight); | |
408 Label ok; | |
409 __ b(pl, &ok); | |
410 __ push(r0); | |
411 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { | |
412 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | |
413 __ push(r2); | |
414 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); | |
415 } else { | |
416 InterruptStub stub; | |
417 __ CallStub(&stub); | |
418 } | |
419 __ pop(r0); | |
420 EmitProfilingCounterReset(); | |
421 __ bind(&ok); | |
422 } | |
374 | 423 |
375 #ifdef DEBUG | 424 #ifdef DEBUG |
376 // Add a label for checking the size of the code used for returning. | 425 // Add a label for checking the size of the code used for returning. |
377 Label check_exit_codesize; | 426 Label check_exit_codesize; |
378 masm_->bind(&check_exit_codesize); | 427 masm_->bind(&check_exit_codesize); |
379 #endif | 428 #endif |
380 // Make sure that the constant pool is not emitted inside of the return | 429 // Make sure that the constant pool is not emitted inside of the return |
381 // sequence. | 430 // sequence. |
382 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 431 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
383 // Here we use masm_-> instead of the __ macro to avoid the code coverage | 432 // Here we use masm_-> instead of the __ macro to avoid the code coverage |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
881 __ cmp(r1, r0); | 930 __ cmp(r1, r0); |
882 __ b(ne, &next_test); | 931 __ b(ne, &next_test); |
883 __ Drop(1); // Switch value is no longer needed. | 932 __ Drop(1); // Switch value is no longer needed. |
884 __ b(clause->body_target()); | 933 __ b(clause->body_target()); |
885 __ bind(&slow_case); | 934 __ bind(&slow_case); |
886 } | 935 } |
887 | 936 |
888 // Record position before stub call for type feedback. | 937 // Record position before stub call for type feedback. |
889 SetSourcePosition(clause->position()); | 938 SetSourcePosition(clause->position()); |
890 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 939 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
891 __ Call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 940 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
892 patch_site.EmitPatchInfo(); | 941 patch_site.EmitPatchInfo(); |
893 | 942 |
894 __ cmp(r0, Operand(0)); | 943 __ cmp(r0, Operand(0)); |
895 __ b(ne, &next_test); | 944 __ b(ne, &next_test); |
896 __ Drop(1); // Switch value is no longer needed. | 945 __ Drop(1); // Switch value is no longer needed. |
897 __ b(clause->body_target()); | 946 __ b(clause->body_target()); |
898 } | 947 } |
899 | 948 |
900 // Discard the test value and jump to the default if present, otherwise to | 949 // Discard the test value and jump to the default if present, otherwise to |
901 // the end of the statement. | 950 // the end of the statement. |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1179 __ b(&loop); | 1228 __ b(&loop); |
1180 __ bind(&fast); | 1229 __ bind(&fast); |
1181 } | 1230 } |
1182 | 1231 |
1183 __ ldr(r0, GlobalObjectOperand()); | 1232 __ ldr(r0, GlobalObjectOperand()); |
1184 __ mov(r2, Operand(var->name())); | 1233 __ mov(r2, Operand(var->name())); |
1185 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1234 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1186 ? RelocInfo::CODE_TARGET | 1235 ? RelocInfo::CODE_TARGET |
1187 : RelocInfo::CODE_TARGET_CONTEXT; | 1236 : RelocInfo::CODE_TARGET_CONTEXT; |
1188 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1237 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1189 __ Call(ic, mode); | 1238 CallIC(ic, mode); |
1190 } | 1239 } |
1191 | 1240 |
1192 | 1241 |
1193 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1242 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1194 Label* slow) { | 1243 Label* slow) { |
1195 ASSERT(var->IsContextSlot()); | 1244 ASSERT(var->IsContextSlot()); |
1196 Register context = cp; | 1245 Register context = cp; |
1197 Register next = r3; | 1246 Register next = r3; |
1198 Register temp = r4; | 1247 Register temp = r4; |
1199 | 1248 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1263 // Three cases: global variables, lookup variables, and all other types of | 1312 // Three cases: global variables, lookup variables, and all other types of |
1264 // variables. | 1313 // variables. |
1265 switch (var->location()) { | 1314 switch (var->location()) { |
1266 case Variable::UNALLOCATED: { | 1315 case Variable::UNALLOCATED: { |
1267 Comment cmnt(masm_, "Global variable"); | 1316 Comment cmnt(masm_, "Global variable"); |
1268 // Use inline caching. Variable name is passed in r2 and the global | 1317 // Use inline caching. Variable name is passed in r2 and the global |
1269 // object (receiver) in r0. | 1318 // object (receiver) in r0. |
1270 __ ldr(r0, GlobalObjectOperand()); | 1319 __ ldr(r0, GlobalObjectOperand()); |
1271 __ mov(r2, Operand(var->name())); | 1320 __ mov(r2, Operand(var->name())); |
1272 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1321 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1273 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1322 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1274 context()->Plug(r0); | 1323 context()->Plug(r0); |
1275 break; | 1324 break; |
1276 } | 1325 } |
1277 | 1326 |
1278 case Variable::PARAMETER: | 1327 case Variable::PARAMETER: |
1279 case Variable::LOCAL: | 1328 case Variable::LOCAL: |
1280 case Variable::CONTEXT: { | 1329 case Variable::CONTEXT: { |
1281 Comment cmnt(masm_, var->IsContextSlot() | 1330 Comment cmnt(masm_, var->IsContextSlot() |
1282 ? "Context variable" | 1331 ? "Context variable" |
1283 : "Stack variable"); | 1332 : "Stack variable"); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1474 // Fall through. | 1523 // Fall through. |
1475 case ObjectLiteral::Property::COMPUTED: | 1524 case ObjectLiteral::Property::COMPUTED: |
1476 if (key->handle()->IsSymbol()) { | 1525 if (key->handle()->IsSymbol()) { |
1477 if (property->emit_store()) { | 1526 if (property->emit_store()) { |
1478 VisitForAccumulatorValue(value); | 1527 VisitForAccumulatorValue(value); |
1479 __ mov(r2, Operand(key->handle())); | 1528 __ mov(r2, Operand(key->handle())); |
1480 __ ldr(r1, MemOperand(sp)); | 1529 __ ldr(r1, MemOperand(sp)); |
1481 Handle<Code> ic = is_classic_mode() | 1530 Handle<Code> ic = is_classic_mode() |
1482 ? isolate()->builtins()->StoreIC_Initialize() | 1531 ? isolate()->builtins()->StoreIC_Initialize() |
1483 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1532 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1484 __ Call(ic, RelocInfo::CODE_TARGET, key->id()); | 1533 CallIC(ic, RelocInfo::CODE_TARGET, key->id()); |
1485 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1534 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1486 } else { | 1535 } else { |
1487 VisitForEffect(value); | 1536 VisitForEffect(value); |
1488 } | 1537 } |
1489 break; | 1538 break; |
1490 } | 1539 } |
1491 // Fall through. | 1540 // Fall through. |
1492 case ObjectLiteral::Property::PROTOTYPE: | 1541 case ObjectLiteral::Property::PROTOTYPE: |
1493 // Duplicate receiver on stack. | 1542 // Duplicate receiver on stack. |
1494 __ ldr(r0, MemOperand(sp)); | 1543 __ ldr(r0, MemOperand(sp)); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1742 } | 1791 } |
1743 } | 1792 } |
1744 | 1793 |
1745 | 1794 |
1746 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1795 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1747 SetSourcePosition(prop->position()); | 1796 SetSourcePosition(prop->position()); |
1748 Literal* key = prop->key()->AsLiteral(); | 1797 Literal* key = prop->key()->AsLiteral(); |
1749 __ mov(r2, Operand(key->handle())); | 1798 __ mov(r2, Operand(key->handle())); |
1750 // Call load IC. It has arguments receiver and property name r0 and r2. | 1799 // Call load IC. It has arguments receiver and property name r0 and r2. |
1751 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1800 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1752 __ Call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1801 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1753 } | 1802 } |
1754 | 1803 |
1755 | 1804 |
1756 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1805 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1757 SetSourcePosition(prop->position()); | 1806 SetSourcePosition(prop->position()); |
1758 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1807 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1759 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1808 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1760 __ Call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1809 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1761 } | 1810 } |
1762 | 1811 |
1763 | 1812 |
1764 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1813 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1765 Token::Value op, | 1814 Token::Value op, |
1766 OverwriteMode mode, | 1815 OverwriteMode mode, |
1767 Expression* left_expr, | 1816 Expression* left_expr, |
1768 Expression* right_expr) { | 1817 Expression* right_expr) { |
1769 Label done, smi_case, stub_call; | 1818 Label done, smi_case, stub_call; |
1770 | 1819 |
1771 Register scratch1 = r2; | 1820 Register scratch1 = r2; |
1772 Register scratch2 = r3; | 1821 Register scratch2 = r3; |
1773 | 1822 |
1774 // Get the arguments. | 1823 // Get the arguments. |
1775 Register left = r1; | 1824 Register left = r1; |
1776 Register right = r0; | 1825 Register right = r0; |
1777 __ pop(left); | 1826 __ pop(left); |
1778 | 1827 |
1779 // Perform combined smi check on both operands. | 1828 // Perform combined smi check on both operands. |
1780 __ orr(scratch1, left, Operand(right)); | 1829 __ orr(scratch1, left, Operand(right)); |
1781 STATIC_ASSERT(kSmiTag == 0); | 1830 STATIC_ASSERT(kSmiTag == 0); |
1782 JumpPatchSite patch_site(masm_); | 1831 JumpPatchSite patch_site(masm_); |
1783 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1832 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
1784 | 1833 |
1785 __ bind(&stub_call); | 1834 __ bind(&stub_call); |
1786 BinaryOpStub stub(op, mode); | 1835 BinaryOpStub stub(op, mode); |
1787 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1836 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1788 patch_site.EmitPatchInfo(); | 1837 patch_site.EmitPatchInfo(); |
1789 __ jmp(&done); | 1838 __ jmp(&done); |
1790 | 1839 |
1791 __ bind(&smi_case); | 1840 __ bind(&smi_case); |
1792 // Smi case. This code works the same way as the smi-smi case in the type | 1841 // Smi case. This code works the same way as the smi-smi case in the type |
1793 // recording binary operation stub, see | 1842 // recording binary operation stub, see |
1794 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 1843 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
1795 switch (op) { | 1844 switch (op) { |
1796 case Token::SAR: | 1845 case Token::SAR: |
1797 __ b(&stub_call); | 1846 __ b(&stub_call); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1860 context()->Plug(r0); | 1909 context()->Plug(r0); |
1861 } | 1910 } |
1862 | 1911 |
1863 | 1912 |
1864 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1913 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
1865 Token::Value op, | 1914 Token::Value op, |
1866 OverwriteMode mode) { | 1915 OverwriteMode mode) { |
1867 __ pop(r1); | 1916 __ pop(r1); |
1868 BinaryOpStub stub(op, mode); | 1917 BinaryOpStub stub(op, mode); |
1869 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1918 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
1870 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1919 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1871 patch_site.EmitPatchInfo(); | 1920 patch_site.EmitPatchInfo(); |
1872 context()->Plug(r0); | 1921 context()->Plug(r0); |
1873 } | 1922 } |
1874 | 1923 |
1875 | 1924 |
1876 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1925 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1877 // Invalid left-hand sides are rewritten to have a 'throw | 1926 // Invalid left-hand sides are rewritten to have a 'throw |
1878 // ReferenceError' on the left-hand side. | 1927 // ReferenceError' on the left-hand side. |
1879 if (!expr->IsValidLeftHandSide()) { | 1928 if (!expr->IsValidLeftHandSide()) { |
1880 VisitForEffect(expr); | 1929 VisitForEffect(expr); |
(...skipping 20 matching lines...) Expand all Loading... | |
1901 } | 1950 } |
1902 case NAMED_PROPERTY: { | 1951 case NAMED_PROPERTY: { |
1903 __ push(r0); // Preserve value. | 1952 __ push(r0); // Preserve value. |
1904 VisitForAccumulatorValue(prop->obj()); | 1953 VisitForAccumulatorValue(prop->obj()); |
1905 __ mov(r1, r0); | 1954 __ mov(r1, r0); |
1906 __ pop(r0); // Restore value. | 1955 __ pop(r0); // Restore value. |
1907 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1956 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
1908 Handle<Code> ic = is_classic_mode() | 1957 Handle<Code> ic = is_classic_mode() |
1909 ? isolate()->builtins()->StoreIC_Initialize() | 1958 ? isolate()->builtins()->StoreIC_Initialize() |
1910 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1959 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1911 __ Call(ic); | 1960 CallIC(ic); |
1912 break; | 1961 break; |
1913 } | 1962 } |
1914 case KEYED_PROPERTY: { | 1963 case KEYED_PROPERTY: { |
1915 __ push(r0); // Preserve value. | 1964 __ push(r0); // Preserve value. |
1916 VisitForStackValue(prop->obj()); | 1965 VisitForStackValue(prop->obj()); |
1917 VisitForAccumulatorValue(prop->key()); | 1966 VisitForAccumulatorValue(prop->key()); |
1918 __ mov(r1, r0); | 1967 __ mov(r1, r0); |
1919 __ pop(r2); | 1968 __ pop(r2); |
1920 __ pop(r0); // Restore value. | 1969 __ pop(r0); // Restore value. |
1921 Handle<Code> ic = is_classic_mode() | 1970 Handle<Code> ic = is_classic_mode() |
1922 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 1971 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1923 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 1972 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1924 __ Call(ic); | 1973 CallIC(ic); |
1925 break; | 1974 break; |
1926 } | 1975 } |
1927 } | 1976 } |
1928 context()->Plug(r0); | 1977 context()->Plug(r0); |
1929 } | 1978 } |
1930 | 1979 |
1931 | 1980 |
1932 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1981 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1933 Token::Value op) { | 1982 Token::Value op) { |
1934 if (var->IsUnallocated()) { | 1983 if (var->IsUnallocated()) { |
1935 // Global var, const, or let. | 1984 // Global var, const, or let. |
1936 __ mov(r2, Operand(var->name())); | 1985 __ mov(r2, Operand(var->name())); |
1937 __ ldr(r1, GlobalObjectOperand()); | 1986 __ ldr(r1, GlobalObjectOperand()); |
1938 Handle<Code> ic = is_classic_mode() | 1987 Handle<Code> ic = is_classic_mode() |
1939 ? isolate()->builtins()->StoreIC_Initialize() | 1988 ? isolate()->builtins()->StoreIC_Initialize() |
1940 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1989 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1941 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1990 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1942 | 1991 |
1943 } else if (op == Token::INIT_CONST) { | 1992 } else if (op == Token::INIT_CONST) { |
1944 // Const initializers need a write barrier. | 1993 // Const initializers need a write barrier. |
1945 ASSERT(!var->IsParameter()); // No const parameters. | 1994 ASSERT(!var->IsParameter()); // No const parameters. |
1946 if (var->IsStackLocal()) { | 1995 if (var->IsStackLocal()) { |
1947 Label skip; | 1996 Label skip; |
1948 __ ldr(r1, StackOperand(var)); | 1997 __ ldr(r1, StackOperand(var)); |
1949 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); | 1998 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); |
1950 __ b(ne, &skip); | 1999 __ b(ne, &skip); |
1951 __ str(result_register(), StackOperand(var)); | 2000 __ str(result_register(), StackOperand(var)); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2049 // receiver into fast case. | 2098 // receiver into fast case. |
2050 if (expr->ends_initialization_block()) { | 2099 if (expr->ends_initialization_block()) { |
2051 __ ldr(r1, MemOperand(sp)); | 2100 __ ldr(r1, MemOperand(sp)); |
2052 } else { | 2101 } else { |
2053 __ pop(r1); | 2102 __ pop(r1); |
2054 } | 2103 } |
2055 | 2104 |
2056 Handle<Code> ic = is_classic_mode() | 2105 Handle<Code> ic = is_classic_mode() |
2057 ? isolate()->builtins()->StoreIC_Initialize() | 2106 ? isolate()->builtins()->StoreIC_Initialize() |
2058 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2107 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2059 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2108 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2060 | 2109 |
2061 // If the assignment ends an initialization block, revert to fast case. | 2110 // If the assignment ends an initialization block, revert to fast case. |
2062 if (expr->ends_initialization_block()) { | 2111 if (expr->ends_initialization_block()) { |
2063 __ push(r0); // Result of assignment, saved even if not needed. | 2112 __ push(r0); // Result of assignment, saved even if not needed. |
2064 // Receiver is under the result value. | 2113 // Receiver is under the result value. |
2065 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2114 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2066 __ push(ip); | 2115 __ push(ip); |
2067 __ CallRuntime(Runtime::kToFastProperties, 1); | 2116 __ CallRuntime(Runtime::kToFastProperties, 1); |
2068 __ pop(r0); | 2117 __ pop(r0); |
2069 __ Drop(1); | 2118 __ Drop(1); |
(...skipping 25 matching lines...) Expand all Loading... | |
2095 // receiver into fast case. | 2144 // receiver into fast case. |
2096 if (expr->ends_initialization_block()) { | 2145 if (expr->ends_initialization_block()) { |
2097 __ ldr(r2, MemOperand(sp)); | 2146 __ ldr(r2, MemOperand(sp)); |
2098 } else { | 2147 } else { |
2099 __ pop(r2); | 2148 __ pop(r2); |
2100 } | 2149 } |
2101 | 2150 |
2102 Handle<Code> ic = is_classic_mode() | 2151 Handle<Code> ic = is_classic_mode() |
2103 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2152 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2104 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2153 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2105 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2154 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2106 | 2155 |
2107 // If the assignment ends an initialization block, revert to fast case. | 2156 // If the assignment ends an initialization block, revert to fast case. |
2108 if (expr->ends_initialization_block()) { | 2157 if (expr->ends_initialization_block()) { |
2109 __ push(r0); // Result of assignment, saved even if not needed. | 2158 __ push(r0); // Result of assignment, saved even if not needed. |
2110 // Receiver is under the result value. | 2159 // Receiver is under the result value. |
2111 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2160 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2112 __ push(ip); | 2161 __ push(ip); |
2113 __ CallRuntime(Runtime::kToFastProperties, 1); | 2162 __ CallRuntime(Runtime::kToFastProperties, 1); |
2114 __ pop(r0); | 2163 __ pop(r0); |
2115 __ Drop(1); | 2164 __ Drop(1); |
(...skipping 13 matching lines...) Expand all Loading... | |
2129 context()->Plug(r0); | 2178 context()->Plug(r0); |
2130 } else { | 2179 } else { |
2131 VisitForStackValue(expr->obj()); | 2180 VisitForStackValue(expr->obj()); |
2132 VisitForAccumulatorValue(expr->key()); | 2181 VisitForAccumulatorValue(expr->key()); |
2133 __ pop(r1); | 2182 __ pop(r1); |
2134 EmitKeyedPropertyLoad(expr); | 2183 EmitKeyedPropertyLoad(expr); |
2135 context()->Plug(r0); | 2184 context()->Plug(r0); |
2136 } | 2185 } |
2137 } | 2186 } |
2138 | 2187 |
2188 | |
2189 void FullCodeGenerator::CallIC(Handle<Code> code, | |
2190 RelocInfo::Mode rmode, | |
2191 unsigned ast_id) { | |
2192 ic_total_count_++; | |
2193 __ Call(code, rmode, ast_id); | |
2194 } | |
2195 | |
2139 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2196 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
2140 Handle<Object> name, | 2197 Handle<Object> name, |
2141 RelocInfo::Mode mode) { | 2198 RelocInfo::Mode mode) { |
2142 // Code common for calls using the IC. | 2199 // Code common for calls using the IC. |
2143 ZoneList<Expression*>* args = expr->arguments(); | 2200 ZoneList<Expression*>* args = expr->arguments(); |
2144 int arg_count = args->length(); | 2201 int arg_count = args->length(); |
2145 { PreservePositionScope scope(masm()->positions_recorder()); | 2202 { PreservePositionScope scope(masm()->positions_recorder()); |
2146 for (int i = 0; i < arg_count; i++) { | 2203 for (int i = 0; i < arg_count; i++) { |
2147 VisitForStackValue(args->at(i)); | 2204 VisitForStackValue(args->at(i)); |
2148 } | 2205 } |
2149 __ mov(r2, Operand(name)); | 2206 __ mov(r2, Operand(name)); |
2150 } | 2207 } |
2151 // Record source position for debugger. | 2208 // Record source position for debugger. |
2152 SetSourcePosition(expr->position()); | 2209 SetSourcePosition(expr->position()); |
2153 // Call the IC initialization code. | 2210 // Call the IC initialization code. |
2154 Handle<Code> ic = | 2211 Handle<Code> ic = |
2155 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2212 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
2156 __ Call(ic, mode, expr->id()); | 2213 CallIC(ic, mode, expr->id()); |
2157 RecordJSReturnSite(expr); | 2214 RecordJSReturnSite(expr); |
2158 // Restore context register. | 2215 // Restore context register. |
2159 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2216 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2160 context()->Plug(r0); | 2217 context()->Plug(r0); |
2161 } | 2218 } |
2162 | 2219 |
2163 | 2220 |
2164 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2221 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2165 Expression* key) { | 2222 Expression* key) { |
2166 // Load the key. | 2223 // Load the key. |
(...skipping 12 matching lines...) Expand all Loading... | |
2179 for (int i = 0; i < arg_count; i++) { | 2236 for (int i = 0; i < arg_count; i++) { |
2180 VisitForStackValue(args->at(i)); | 2237 VisitForStackValue(args->at(i)); |
2181 } | 2238 } |
2182 } | 2239 } |
2183 // Record source position for debugger. | 2240 // Record source position for debugger. |
2184 SetSourcePosition(expr->position()); | 2241 SetSourcePosition(expr->position()); |
2185 // Call the IC initialization code. | 2242 // Call the IC initialization code. |
2186 Handle<Code> ic = | 2243 Handle<Code> ic = |
2187 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2244 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
2188 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2245 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2189 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2246 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2190 RecordJSReturnSite(expr); | 2247 RecordJSReturnSite(expr); |
2191 // Restore context register. | 2248 // Restore context register. |
2192 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2249 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2193 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2250 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
2194 } | 2251 } |
2195 | 2252 |
2196 | 2253 |
2197 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2254 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2198 // Code common for calls using the call stub. | 2255 // Code common for calls using the call stub. |
2199 ZoneList<Expression*>* args = expr->arguments(); | 2256 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 1576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3776 for (int i = 0; i < arg_count; i++) { | 3833 for (int i = 0; i < arg_count; i++) { |
3777 VisitForStackValue(args->at(i)); | 3834 VisitForStackValue(args->at(i)); |
3778 } | 3835 } |
3779 | 3836 |
3780 if (expr->is_jsruntime()) { | 3837 if (expr->is_jsruntime()) { |
3781 // Call the JS runtime function. | 3838 // Call the JS runtime function. |
3782 __ mov(r2, Operand(expr->name())); | 3839 __ mov(r2, Operand(expr->name())); |
3783 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3840 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3784 Handle<Code> ic = | 3841 Handle<Code> ic = |
3785 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 3842 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
3786 __ Call(ic, mode, expr->id()); | 3843 CallIC(ic, mode, expr->id()); |
3787 // Restore context register. | 3844 // Restore context register. |
3788 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3845 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3789 } else { | 3846 } else { |
3790 // Call the C runtime function. | 3847 // Call the C runtime function. |
3791 __ CallRuntime(expr->function(), arg_count); | 3848 __ CallRuntime(expr->function(), arg_count); |
3792 } | 3849 } |
3793 context()->Plug(r0); | 3850 context()->Plug(r0); |
3794 } | 3851 } |
3795 | 3852 |
3796 | 3853 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3931 // TODO(svenpanne): Allowing format strings in Comment would be nice here... | 3988 // TODO(svenpanne): Allowing format strings in Comment would be nice here... |
3932 Comment cmt(masm_, comment); | 3989 Comment cmt(masm_, comment); |
3933 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); | 3990 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
3934 UnaryOverwriteMode overwrite = | 3991 UnaryOverwriteMode overwrite = |
3935 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 3992 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
3936 UnaryOpStub stub(expr->op(), overwrite); | 3993 UnaryOpStub stub(expr->op(), overwrite); |
3937 // UnaryOpStub expects the argument to be in the | 3994 // UnaryOpStub expects the argument to be in the |
3938 // accumulator register r0. | 3995 // accumulator register r0. |
3939 VisitForAccumulatorValue(expr->expression()); | 3996 VisitForAccumulatorValue(expr->expression()); |
3940 SetSourcePosition(expr->position()); | 3997 SetSourcePosition(expr->position()); |
3941 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 3998 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
3942 context()->Plug(r0); | 3999 context()->Plug(r0); |
3943 } | 4000 } |
3944 | 4001 |
3945 | 4002 |
3946 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4003 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
3947 Comment cmnt(masm_, "[ CountOperation"); | 4004 Comment cmnt(masm_, "[ CountOperation"); |
3948 SetSourcePosition(expr->position()); | 4005 SetSourcePosition(expr->position()); |
3949 | 4006 |
3950 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 4007 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
3951 // as the left-hand side. | 4008 // as the left-hand side. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4042 __ bind(&stub_call); | 4099 __ bind(&stub_call); |
4043 // Call stub. Undo operation first. | 4100 // Call stub. Undo operation first. |
4044 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 4101 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
4045 } | 4102 } |
4046 __ mov(r1, Operand(Smi::FromInt(count_value))); | 4103 __ mov(r1, Operand(Smi::FromInt(count_value))); |
4047 | 4104 |
4048 // Record position before stub call. | 4105 // Record position before stub call. |
4049 SetSourcePosition(expr->position()); | 4106 SetSourcePosition(expr->position()); |
4050 | 4107 |
4051 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 4108 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
4052 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); | 4109 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
4053 patch_site.EmitPatchInfo(); | 4110 patch_site.EmitPatchInfo(); |
4054 __ bind(&done); | 4111 __ bind(&done); |
4055 | 4112 |
4056 // Store the value returned in r0. | 4113 // Store the value returned in r0. |
4057 switch (assign_type) { | 4114 switch (assign_type) { |
4058 case VARIABLE: | 4115 case VARIABLE: |
4059 if (expr->is_postfix()) { | 4116 if (expr->is_postfix()) { |
4060 { EffectContext context(this); | 4117 { EffectContext context(this); |
4061 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4118 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
4062 Token::ASSIGN); | 4119 Token::ASSIGN); |
(...skipping 11 matching lines...) Expand all Loading... | |
4074 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4131 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4075 context()->Plug(r0); | 4132 context()->Plug(r0); |
4076 } | 4133 } |
4077 break; | 4134 break; |
4078 case NAMED_PROPERTY: { | 4135 case NAMED_PROPERTY: { |
4079 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 4136 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
4080 __ pop(r1); | 4137 __ pop(r1); |
4081 Handle<Code> ic = is_classic_mode() | 4138 Handle<Code> ic = is_classic_mode() |
4082 ? isolate()->builtins()->StoreIC_Initialize() | 4139 ? isolate()->builtins()->StoreIC_Initialize() |
4083 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 4140 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
4084 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4141 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4085 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4142 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4086 if (expr->is_postfix()) { | 4143 if (expr->is_postfix()) { |
4087 if (!context()->IsEffect()) { | 4144 if (!context()->IsEffect()) { |
4088 context()->PlugTOS(); | 4145 context()->PlugTOS(); |
4089 } | 4146 } |
4090 } else { | 4147 } else { |
4091 context()->Plug(r0); | 4148 context()->Plug(r0); |
4092 } | 4149 } |
4093 break; | 4150 break; |
4094 } | 4151 } |
4095 case KEYED_PROPERTY: { | 4152 case KEYED_PROPERTY: { |
4096 __ pop(r1); // Key. | 4153 __ pop(r1); // Key. |
4097 __ pop(r2); // Receiver. | 4154 __ pop(r2); // Receiver. |
4098 Handle<Code> ic = is_classic_mode() | 4155 Handle<Code> ic = is_classic_mode() |
4099 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4156 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4100 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4157 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4101 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4158 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4102 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4159 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4103 if (expr->is_postfix()) { | 4160 if (expr->is_postfix()) { |
4104 if (!context()->IsEffect()) { | 4161 if (!context()->IsEffect()) { |
4105 context()->PlugTOS(); | 4162 context()->PlugTOS(); |
4106 } | 4163 } |
4107 } else { | 4164 } else { |
4108 context()->Plug(r0); | 4165 context()->Plug(r0); |
4109 } | 4166 } |
4110 break; | 4167 break; |
4111 } | 4168 } |
4112 } | 4169 } |
4113 } | 4170 } |
4114 | 4171 |
4115 | 4172 |
4116 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4173 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4117 ASSERT(!context()->IsEffect()); | 4174 ASSERT(!context()->IsEffect()); |
4118 ASSERT(!context()->IsTest()); | 4175 ASSERT(!context()->IsTest()); |
4119 VariableProxy* proxy = expr->AsVariableProxy(); | 4176 VariableProxy* proxy = expr->AsVariableProxy(); |
4120 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4177 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4121 Comment cmnt(masm_, "Global variable"); | 4178 Comment cmnt(masm_, "Global variable"); |
4122 __ ldr(r0, GlobalObjectOperand()); | 4179 __ ldr(r0, GlobalObjectOperand()); |
4123 __ mov(r2, Operand(proxy->name())); | 4180 __ mov(r2, Operand(proxy->name())); |
4124 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 4181 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
4125 // Use a regular load, not a contextual load, to avoid a reference | 4182 // Use a regular load, not a contextual load, to avoid a reference |
4126 // error. | 4183 // error. |
4127 __ Call(ic); | 4184 CallIC(ic); |
4128 PrepareForBailout(expr, TOS_REG); | 4185 PrepareForBailout(expr, TOS_REG); |
4129 context()->Plug(r0); | 4186 context()->Plug(r0); |
4130 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4187 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
4131 Label done, slow; | 4188 Label done, slow; |
4132 | 4189 |
4133 // Generate code for loading from variables potentially shadowed | 4190 // Generate code for loading from variables potentially shadowed |
4134 // by eval-introduced variables. | 4191 // by eval-introduced variables. |
4135 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4192 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
4136 | 4193 |
4137 __ bind(&slow); | 4194 __ bind(&slow); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4300 __ orr(r2, r0, Operand(r1)); | 4357 __ orr(r2, r0, Operand(r1)); |
4301 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4358 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
4302 __ cmp(r1, r0); | 4359 __ cmp(r1, r0); |
4303 Split(cond, if_true, if_false, NULL); | 4360 Split(cond, if_true, if_false, NULL); |
4304 __ bind(&slow_case); | 4361 __ bind(&slow_case); |
4305 } | 4362 } |
4306 | 4363 |
4307 // Record position and call the compare IC. | 4364 // Record position and call the compare IC. |
4308 SetSourcePosition(expr->position()); | 4365 SetSourcePosition(expr->position()); |
4309 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4366 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4310 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4367 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4311 patch_site.EmitPatchInfo(); | 4368 patch_site.EmitPatchInfo(); |
4312 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4369 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4313 __ cmp(r0, Operand(0)); | 4370 __ cmp(r0, Operand(0)); |
4314 Split(cond, if_true, if_false, fall_through); | 4371 Split(cond, if_true, if_false, fall_through); |
4315 } | 4372 } |
4316 } | 4373 } |
4317 | 4374 |
4318 // Convert the result of the comparison into one expected for this | 4375 // Convert the result of the comparison into one expected for this |
4319 // expression's context. | 4376 // expression's context. |
4320 context()->Plug(if_true, if_false); | 4377 context()->Plug(if_true, if_false); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4462 *context_length = 0; | 4519 *context_length = 0; |
4463 return previous_; | 4520 return previous_; |
4464 } | 4521 } |
4465 | 4522 |
4466 | 4523 |
4467 #undef __ | 4524 #undef __ |
4468 | 4525 |
4469 } } // namespace v8::internal | 4526 } } // namespace v8::internal |
4470 | 4527 |
4471 #endif // V8_TARGET_ARCH_ARM | 4528 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |