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. |
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 // Detect debug break requests as soon as possible. |
| 337 reset_value = 10; |
| 338 } |
| 339 __ mov(r2, Operand(profiling_counter_)); |
| 340 __ mov(r3, Operand(Smi::FromInt(reset_value))); |
| 341 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); |
| 342 } |
| 343 |
| 344 |
| 345 static const int kMaxBackEdgeWeight = 127; |
| 346 static const int kBackEdgeDistanceDivisor = 142; |
| 347 |
| 348 |
339 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, | 349 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, |
340 Label* back_edge_target) { | 350 Label* back_edge_target) { |
341 Comment cmnt(masm_, "[ Stack check"); | 351 Comment cmnt(masm_, "[ Stack check"); |
342 Label ok; | 352 Label ok; |
343 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 353 |
344 __ cmp(sp, Operand(ip)); | 354 if (FLAG_count_based_interrupts) { |
345 __ b(hs, &ok); | 355 int weight = 1; |
346 StackCheckStub stub; | 356 if (FLAG_weighted_back_edges) { |
347 __ CallStub(&stub); | 357 ASSERT(back_edge_target->is_bound()); |
| 358 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); |
| 359 weight = Min(kMaxBackEdgeWeight, |
| 360 Max(1, distance / kBackEdgeDistanceDivisor)); |
| 361 } |
| 362 EmitProfilingCounterDecrement(weight); |
| 363 __ b(pl, &ok); |
| 364 InterruptStub stub; |
| 365 __ CallStub(&stub); |
| 366 } else { |
| 367 __ LoadRoot(ip, Heap::kStackLimitRootIndex); |
| 368 __ cmp(sp, Operand(ip)); |
| 369 __ b(hs, &ok); |
| 370 StackCheckStub stub; |
| 371 __ CallStub(&stub); |
| 372 } |
| 373 |
348 // Record a mapping of this PC offset to the OSR id. This is used to find | 374 // 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 | 375 // 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. | 376 // the deoptimization input data found in the optimized code. |
351 RecordStackCheck(stmt->OsrEntryId()); | 377 RecordStackCheck(stmt->OsrEntryId()); |
352 | 378 |
| 379 if (FLAG_count_based_interrupts) { |
| 380 EmitProfilingCounterReset(); |
| 381 } |
| 382 |
353 __ bind(&ok); | 383 __ bind(&ok); |
354 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); | 384 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); |
355 // Record a mapping of the OSR id to this PC. This is used if the OSR | 385 // 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 | 386 // entry becomes the target of a bailout. We don't expect it to be, but |
357 // we want it to work if it is. | 387 // we want it to work if it is. |
358 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); | 388 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); |
359 } | 389 } |
360 | 390 |
361 | 391 |
362 void FullCodeGenerator::EmitReturnSequence() { | 392 void FullCodeGenerator::EmitReturnSequence() { |
363 Comment cmnt(masm_, "[ Return sequence"); | 393 Comment cmnt(masm_, "[ Return sequence"); |
364 if (return_label_.is_bound()) { | 394 if (return_label_.is_bound()) { |
365 __ b(&return_label_); | 395 __ b(&return_label_); |
366 } else { | 396 } else { |
367 __ bind(&return_label_); | 397 __ bind(&return_label_); |
368 if (FLAG_trace) { | 398 if (FLAG_trace) { |
369 // Push the return value on the stack as the parameter. | 399 // Push the return value on the stack as the parameter. |
370 // Runtime::TraceExit returns its parameter in r0. | 400 // Runtime::TraceExit returns its parameter in r0. |
371 __ push(r0); | 401 __ push(r0); |
372 __ CallRuntime(Runtime::kTraceExit, 1); | 402 __ CallRuntime(Runtime::kTraceExit, 1); |
373 } | 403 } |
| 404 if (FLAG_interrupt_at_exit || FLAG_self_optimization) { |
| 405 // Pretend that the exit is a backwards jump to the entry. |
| 406 int weight = 1; |
| 407 if (info_->ShouldSelfOptimize()) { |
| 408 weight = FLAG_interrupt_budget / FLAG_self_opt_count; |
| 409 } else if (FLAG_weighted_back_edges) { |
| 410 int distance = masm_->pc_offset(); |
| 411 weight = Min(kMaxBackEdgeWeight, |
| 412 Max(1, distance / kBackEdgeDistanceDivisor)); |
| 413 } |
| 414 EmitProfilingCounterDecrement(weight); |
| 415 Label ok; |
| 416 __ b(pl, &ok); |
| 417 __ push(r0); |
| 418 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { |
| 419 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 420 __ push(r2); |
| 421 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); |
| 422 } else { |
| 423 InterruptStub stub; |
| 424 __ CallStub(&stub); |
| 425 } |
| 426 __ pop(r0); |
| 427 EmitProfilingCounterReset(); |
| 428 __ bind(&ok); |
| 429 } |
374 | 430 |
375 #ifdef DEBUG | 431 #ifdef DEBUG |
376 // Add a label for checking the size of the code used for returning. | 432 // Add a label for checking the size of the code used for returning. |
377 Label check_exit_codesize; | 433 Label check_exit_codesize; |
378 masm_->bind(&check_exit_codesize); | 434 masm_->bind(&check_exit_codesize); |
379 #endif | 435 #endif |
380 // Make sure that the constant pool is not emitted inside of the return | 436 // Make sure that the constant pool is not emitted inside of the return |
381 // sequence. | 437 // sequence. |
382 { Assembler::BlockConstPoolScope block_const_pool(masm_); | 438 { Assembler::BlockConstPoolScope block_const_pool(masm_); |
383 // Here we use masm_-> instead of the __ macro to avoid the code coverage | 439 // 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); | 937 __ cmp(r1, r0); |
882 __ b(ne, &next_test); | 938 __ b(ne, &next_test); |
883 __ Drop(1); // Switch value is no longer needed. | 939 __ Drop(1); // Switch value is no longer needed. |
884 __ b(clause->body_target()); | 940 __ b(clause->body_target()); |
885 __ bind(&slow_case); | 941 __ bind(&slow_case); |
886 } | 942 } |
887 | 943 |
888 // Record position before stub call for type feedback. | 944 // Record position before stub call for type feedback. |
889 SetSourcePosition(clause->position()); | 945 SetSourcePosition(clause->position()); |
890 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 946 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); |
891 __ Call(ic, RelocInfo::CODE_TARGET, clause->CompareId()); | 947 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); |
892 patch_site.EmitPatchInfo(); | 948 patch_site.EmitPatchInfo(); |
893 | 949 |
894 __ cmp(r0, Operand(0)); | 950 __ cmp(r0, Operand(0)); |
895 __ b(ne, &next_test); | 951 __ b(ne, &next_test); |
896 __ Drop(1); // Switch value is no longer needed. | 952 __ Drop(1); // Switch value is no longer needed. |
897 __ b(clause->body_target()); | 953 __ b(clause->body_target()); |
898 } | 954 } |
899 | 955 |
900 // Discard the test value and jump to the default if present, otherwise to | 956 // Discard the test value and jump to the default if present, otherwise to |
901 // the end of the statement. | 957 // the end of the statement. |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1179 __ b(&loop); | 1235 __ b(&loop); |
1180 __ bind(&fast); | 1236 __ bind(&fast); |
1181 } | 1237 } |
1182 | 1238 |
1183 __ ldr(r0, GlobalObjectOperand()); | 1239 __ ldr(r0, GlobalObjectOperand()); |
1184 __ mov(r2, Operand(var->name())); | 1240 __ mov(r2, Operand(var->name())); |
1185 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) | 1241 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) |
1186 ? RelocInfo::CODE_TARGET | 1242 ? RelocInfo::CODE_TARGET |
1187 : RelocInfo::CODE_TARGET_CONTEXT; | 1243 : RelocInfo::CODE_TARGET_CONTEXT; |
1188 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1244 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1189 __ Call(ic, mode); | 1245 CallIC(ic, mode); |
1190 } | 1246 } |
1191 | 1247 |
1192 | 1248 |
1193 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1249 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
1194 Label* slow) { | 1250 Label* slow) { |
1195 ASSERT(var->IsContextSlot()); | 1251 ASSERT(var->IsContextSlot()); |
1196 Register context = cp; | 1252 Register context = cp; |
1197 Register next = r3; | 1253 Register next = r3; |
1198 Register temp = r4; | 1254 Register temp = r4; |
1199 | 1255 |
(...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 | 1319 // Three cases: global variables, lookup variables, and all other types of |
1264 // variables. | 1320 // variables. |
1265 switch (var->location()) { | 1321 switch (var->location()) { |
1266 case Variable::UNALLOCATED: { | 1322 case Variable::UNALLOCATED: { |
1267 Comment cmnt(masm_, "Global variable"); | 1323 Comment cmnt(masm_, "Global variable"); |
1268 // Use inline caching. Variable name is passed in r2 and the global | 1324 // Use inline caching. Variable name is passed in r2 and the global |
1269 // object (receiver) in r0. | 1325 // object (receiver) in r0. |
1270 __ ldr(r0, GlobalObjectOperand()); | 1326 __ ldr(r0, GlobalObjectOperand()); |
1271 __ mov(r2, Operand(var->name())); | 1327 __ mov(r2, Operand(var->name())); |
1272 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1328 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1273 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1329 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1274 context()->Plug(r0); | 1330 context()->Plug(r0); |
1275 break; | 1331 break; |
1276 } | 1332 } |
1277 | 1333 |
1278 case Variable::PARAMETER: | 1334 case Variable::PARAMETER: |
1279 case Variable::LOCAL: | 1335 case Variable::LOCAL: |
1280 case Variable::CONTEXT: { | 1336 case Variable::CONTEXT: { |
1281 Comment cmnt(masm_, var->IsContextSlot() | 1337 Comment cmnt(masm_, var->IsContextSlot() |
1282 ? "Context variable" | 1338 ? "Context variable" |
1283 : "Stack variable"); | 1339 : "Stack variable"); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1474 // Fall through. | 1530 // Fall through. |
1475 case ObjectLiteral::Property::COMPUTED: | 1531 case ObjectLiteral::Property::COMPUTED: |
1476 if (key->handle()->IsSymbol()) { | 1532 if (key->handle()->IsSymbol()) { |
1477 if (property->emit_store()) { | 1533 if (property->emit_store()) { |
1478 VisitForAccumulatorValue(value); | 1534 VisitForAccumulatorValue(value); |
1479 __ mov(r2, Operand(key->handle())); | 1535 __ mov(r2, Operand(key->handle())); |
1480 __ ldr(r1, MemOperand(sp)); | 1536 __ ldr(r1, MemOperand(sp)); |
1481 Handle<Code> ic = is_classic_mode() | 1537 Handle<Code> ic = is_classic_mode() |
1482 ? isolate()->builtins()->StoreIC_Initialize() | 1538 ? isolate()->builtins()->StoreIC_Initialize() |
1483 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1539 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1484 __ Call(ic, RelocInfo::CODE_TARGET, key->id()); | 1540 CallIC(ic, RelocInfo::CODE_TARGET, key->id()); |
1485 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1541 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1486 } else { | 1542 } else { |
1487 VisitForEffect(value); | 1543 VisitForEffect(value); |
1488 } | 1544 } |
1489 break; | 1545 break; |
1490 } | 1546 } |
1491 // Fall through. | 1547 // Fall through. |
1492 case ObjectLiteral::Property::PROTOTYPE: | 1548 case ObjectLiteral::Property::PROTOTYPE: |
1493 // Duplicate receiver on stack. | 1549 // Duplicate receiver on stack. |
1494 __ ldr(r0, MemOperand(sp)); | 1550 __ ldr(r0, MemOperand(sp)); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1742 } | 1798 } |
1743 } | 1799 } |
1744 | 1800 |
1745 | 1801 |
1746 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1802 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1747 SetSourcePosition(prop->position()); | 1803 SetSourcePosition(prop->position()); |
1748 Literal* key = prop->key()->AsLiteral(); | 1804 Literal* key = prop->key()->AsLiteral(); |
1749 __ mov(r2, Operand(key->handle())); | 1805 __ mov(r2, Operand(key->handle())); |
1750 // Call load IC. It has arguments receiver and property name r0 and r2. | 1806 // Call load IC. It has arguments receiver and property name r0 and r2. |
1751 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 1807 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
1752 __ Call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1808 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1753 } | 1809 } |
1754 | 1810 |
1755 | 1811 |
1756 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1812 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1757 SetSourcePosition(prop->position()); | 1813 SetSourcePosition(prop->position()); |
1758 // Call keyed load IC. It has arguments key and receiver in r0 and r1. | 1814 // Call keyed load IC. It has arguments key and receiver in r0 and r1. |
1759 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 1815 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
1760 __ Call(ic, RelocInfo::CODE_TARGET, prop->id()); | 1816 CallIC(ic, RelocInfo::CODE_TARGET, prop->id()); |
1761 } | 1817 } |
1762 | 1818 |
1763 | 1819 |
1764 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 1820 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
1765 Token::Value op, | 1821 Token::Value op, |
1766 OverwriteMode mode, | 1822 OverwriteMode mode, |
1767 Expression* left_expr, | 1823 Expression* left_expr, |
1768 Expression* right_expr) { | 1824 Expression* right_expr) { |
1769 Label done, smi_case, stub_call; | 1825 Label done, smi_case, stub_call; |
1770 | 1826 |
1771 Register scratch1 = r2; | 1827 Register scratch1 = r2; |
1772 Register scratch2 = r3; | 1828 Register scratch2 = r3; |
1773 | 1829 |
1774 // Get the arguments. | 1830 // Get the arguments. |
1775 Register left = r1; | 1831 Register left = r1; |
1776 Register right = r0; | 1832 Register right = r0; |
1777 __ pop(left); | 1833 __ pop(left); |
1778 | 1834 |
1779 // Perform combined smi check on both operands. | 1835 // Perform combined smi check on both operands. |
1780 __ orr(scratch1, left, Operand(right)); | 1836 __ orr(scratch1, left, Operand(right)); |
1781 STATIC_ASSERT(kSmiTag == 0); | 1837 STATIC_ASSERT(kSmiTag == 0); |
1782 JumpPatchSite patch_site(masm_); | 1838 JumpPatchSite patch_site(masm_); |
1783 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 1839 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
1784 | 1840 |
1785 __ bind(&stub_call); | 1841 __ bind(&stub_call); |
1786 BinaryOpStub stub(op, mode); | 1842 BinaryOpStub stub(op, mode); |
1787 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1843 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1788 patch_site.EmitPatchInfo(); | 1844 patch_site.EmitPatchInfo(); |
1789 __ jmp(&done); | 1845 __ jmp(&done); |
1790 | 1846 |
1791 __ bind(&smi_case); | 1847 __ bind(&smi_case); |
1792 // Smi case. This code works the same way as the smi-smi case in the type | 1848 // Smi case. This code works the same way as the smi-smi case in the type |
1793 // recording binary operation stub, see | 1849 // recording binary operation stub, see |
1794 // BinaryOpStub::GenerateSmiSmiOperation for comments. | 1850 // BinaryOpStub::GenerateSmiSmiOperation for comments. |
1795 switch (op) { | 1851 switch (op) { |
1796 case Token::SAR: | 1852 case Token::SAR: |
1797 __ b(&stub_call); | 1853 __ b(&stub_call); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1860 context()->Plug(r0); | 1916 context()->Plug(r0); |
1861 } | 1917 } |
1862 | 1918 |
1863 | 1919 |
1864 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, | 1920 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, |
1865 Token::Value op, | 1921 Token::Value op, |
1866 OverwriteMode mode) { | 1922 OverwriteMode mode) { |
1867 __ pop(r1); | 1923 __ pop(r1); |
1868 BinaryOpStub stub(op, mode); | 1924 BinaryOpStub stub(op, mode); |
1869 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 1925 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
1870 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 1926 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
1871 patch_site.EmitPatchInfo(); | 1927 patch_site.EmitPatchInfo(); |
1872 context()->Plug(r0); | 1928 context()->Plug(r0); |
1873 } | 1929 } |
1874 | 1930 |
1875 | 1931 |
1876 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1932 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
1877 // Invalid left-hand sides are rewritten to have a 'throw | 1933 // Invalid left-hand sides are rewritten to have a 'throw |
1878 // ReferenceError' on the left-hand side. | 1934 // ReferenceError' on the left-hand side. |
1879 if (!expr->IsValidLeftHandSide()) { | 1935 if (!expr->IsValidLeftHandSide()) { |
1880 VisitForEffect(expr); | 1936 VisitForEffect(expr); |
(...skipping 20 matching lines...) Expand all Loading... |
1901 } | 1957 } |
1902 case NAMED_PROPERTY: { | 1958 case NAMED_PROPERTY: { |
1903 __ push(r0); // Preserve value. | 1959 __ push(r0); // Preserve value. |
1904 VisitForAccumulatorValue(prop->obj()); | 1960 VisitForAccumulatorValue(prop->obj()); |
1905 __ mov(r1, r0); | 1961 __ mov(r1, r0); |
1906 __ pop(r0); // Restore value. | 1962 __ pop(r0); // Restore value. |
1907 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1963 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
1908 Handle<Code> ic = is_classic_mode() | 1964 Handle<Code> ic = is_classic_mode() |
1909 ? isolate()->builtins()->StoreIC_Initialize() | 1965 ? isolate()->builtins()->StoreIC_Initialize() |
1910 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1966 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1911 __ Call(ic); | 1967 CallIC(ic); |
1912 break; | 1968 break; |
1913 } | 1969 } |
1914 case KEYED_PROPERTY: { | 1970 case KEYED_PROPERTY: { |
1915 __ push(r0); // Preserve value. | 1971 __ push(r0); // Preserve value. |
1916 VisitForStackValue(prop->obj()); | 1972 VisitForStackValue(prop->obj()); |
1917 VisitForAccumulatorValue(prop->key()); | 1973 VisitForAccumulatorValue(prop->key()); |
1918 __ mov(r1, r0); | 1974 __ mov(r1, r0); |
1919 __ pop(r2); | 1975 __ pop(r2); |
1920 __ pop(r0); // Restore value. | 1976 __ pop(r0); // Restore value. |
1921 Handle<Code> ic = is_classic_mode() | 1977 Handle<Code> ic = is_classic_mode() |
1922 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 1978 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
1923 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 1979 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
1924 __ Call(ic); | 1980 CallIC(ic); |
1925 break; | 1981 break; |
1926 } | 1982 } |
1927 } | 1983 } |
1928 context()->Plug(r0); | 1984 context()->Plug(r0); |
1929 } | 1985 } |
1930 | 1986 |
1931 | 1987 |
1932 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 1988 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1933 Token::Value op) { | 1989 Token::Value op) { |
1934 if (var->IsUnallocated()) { | 1990 if (var->IsUnallocated()) { |
1935 // Global var, const, or let. | 1991 // Global var, const, or let. |
1936 __ mov(r2, Operand(var->name())); | 1992 __ mov(r2, Operand(var->name())); |
1937 __ ldr(r1, GlobalObjectOperand()); | 1993 __ ldr(r1, GlobalObjectOperand()); |
1938 Handle<Code> ic = is_classic_mode() | 1994 Handle<Code> ic = is_classic_mode() |
1939 ? isolate()->builtins()->StoreIC_Initialize() | 1995 ? isolate()->builtins()->StoreIC_Initialize() |
1940 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1996 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1941 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 1997 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); |
1942 | 1998 |
1943 } else if (op == Token::INIT_CONST) { | 1999 } else if (op == Token::INIT_CONST) { |
1944 // Const initializers need a write barrier. | 2000 // Const initializers need a write barrier. |
1945 ASSERT(!var->IsParameter()); // No const parameters. | 2001 ASSERT(!var->IsParameter()); // No const parameters. |
1946 if (var->IsStackLocal()) { | 2002 if (var->IsStackLocal()) { |
1947 Label skip; | 2003 Label skip; |
1948 __ ldr(r1, StackOperand(var)); | 2004 __ ldr(r1, StackOperand(var)); |
1949 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); | 2005 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); |
1950 __ b(ne, &skip); | 2006 __ b(ne, &skip); |
1951 __ str(result_register(), StackOperand(var)); | 2007 __ str(result_register(), StackOperand(var)); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2049 // receiver into fast case. | 2105 // receiver into fast case. |
2050 if (expr->ends_initialization_block()) { | 2106 if (expr->ends_initialization_block()) { |
2051 __ ldr(r1, MemOperand(sp)); | 2107 __ ldr(r1, MemOperand(sp)); |
2052 } else { | 2108 } else { |
2053 __ pop(r1); | 2109 __ pop(r1); |
2054 } | 2110 } |
2055 | 2111 |
2056 Handle<Code> ic = is_classic_mode() | 2112 Handle<Code> ic = is_classic_mode() |
2057 ? isolate()->builtins()->StoreIC_Initialize() | 2113 ? isolate()->builtins()->StoreIC_Initialize() |
2058 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2114 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
2059 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2115 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2060 | 2116 |
2061 // If the assignment ends an initialization block, revert to fast case. | 2117 // If the assignment ends an initialization block, revert to fast case. |
2062 if (expr->ends_initialization_block()) { | 2118 if (expr->ends_initialization_block()) { |
2063 __ push(r0); // Result of assignment, saved even if not needed. | 2119 __ push(r0); // Result of assignment, saved even if not needed. |
2064 // Receiver is under the result value. | 2120 // Receiver is under the result value. |
2065 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2121 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2066 __ push(ip); | 2122 __ push(ip); |
2067 __ CallRuntime(Runtime::kToFastProperties, 1); | 2123 __ CallRuntime(Runtime::kToFastProperties, 1); |
2068 __ pop(r0); | 2124 __ pop(r0); |
2069 __ Drop(1); | 2125 __ Drop(1); |
(...skipping 25 matching lines...) Expand all Loading... |
2095 // receiver into fast case. | 2151 // receiver into fast case. |
2096 if (expr->ends_initialization_block()) { | 2152 if (expr->ends_initialization_block()) { |
2097 __ ldr(r2, MemOperand(sp)); | 2153 __ ldr(r2, MemOperand(sp)); |
2098 } else { | 2154 } else { |
2099 __ pop(r2); | 2155 __ pop(r2); |
2100 } | 2156 } |
2101 | 2157 |
2102 Handle<Code> ic = is_classic_mode() | 2158 Handle<Code> ic = is_classic_mode() |
2103 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2159 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
2104 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2160 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
2105 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2161 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2106 | 2162 |
2107 // If the assignment ends an initialization block, revert to fast case. | 2163 // If the assignment ends an initialization block, revert to fast case. |
2108 if (expr->ends_initialization_block()) { | 2164 if (expr->ends_initialization_block()) { |
2109 __ push(r0); // Result of assignment, saved even if not needed. | 2165 __ push(r0); // Result of assignment, saved even if not needed. |
2110 // Receiver is under the result value. | 2166 // Receiver is under the result value. |
2111 __ ldr(ip, MemOperand(sp, kPointerSize)); | 2167 __ ldr(ip, MemOperand(sp, kPointerSize)); |
2112 __ push(ip); | 2168 __ push(ip); |
2113 __ CallRuntime(Runtime::kToFastProperties, 1); | 2169 __ CallRuntime(Runtime::kToFastProperties, 1); |
2114 __ pop(r0); | 2170 __ pop(r0); |
2115 __ Drop(1); | 2171 __ Drop(1); |
(...skipping 13 matching lines...) Expand all Loading... |
2129 context()->Plug(r0); | 2185 context()->Plug(r0); |
2130 } else { | 2186 } else { |
2131 VisitForStackValue(expr->obj()); | 2187 VisitForStackValue(expr->obj()); |
2132 VisitForAccumulatorValue(expr->key()); | 2188 VisitForAccumulatorValue(expr->key()); |
2133 __ pop(r1); | 2189 __ pop(r1); |
2134 EmitKeyedPropertyLoad(expr); | 2190 EmitKeyedPropertyLoad(expr); |
2135 context()->Plug(r0); | 2191 context()->Plug(r0); |
2136 } | 2192 } |
2137 } | 2193 } |
2138 | 2194 |
| 2195 |
| 2196 void FullCodeGenerator::CallIC(Handle<Code> code, |
| 2197 RelocInfo::Mode rmode, |
| 2198 unsigned ast_id) { |
| 2199 ic_total_count_++; |
| 2200 __ Call(code, rmode, ast_id); |
| 2201 } |
| 2202 |
2139 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 2203 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
2140 Handle<Object> name, | 2204 Handle<Object> name, |
2141 RelocInfo::Mode mode) { | 2205 RelocInfo::Mode mode) { |
2142 // Code common for calls using the IC. | 2206 // Code common for calls using the IC. |
2143 ZoneList<Expression*>* args = expr->arguments(); | 2207 ZoneList<Expression*>* args = expr->arguments(); |
2144 int arg_count = args->length(); | 2208 int arg_count = args->length(); |
2145 { PreservePositionScope scope(masm()->positions_recorder()); | 2209 { PreservePositionScope scope(masm()->positions_recorder()); |
2146 for (int i = 0; i < arg_count; i++) { | 2210 for (int i = 0; i < arg_count; i++) { |
2147 VisitForStackValue(args->at(i)); | 2211 VisitForStackValue(args->at(i)); |
2148 } | 2212 } |
2149 __ mov(r2, Operand(name)); | 2213 __ mov(r2, Operand(name)); |
2150 } | 2214 } |
2151 // Record source position for debugger. | 2215 // Record source position for debugger. |
2152 SetSourcePosition(expr->position()); | 2216 SetSourcePosition(expr->position()); |
2153 // Call the IC initialization code. | 2217 // Call the IC initialization code. |
2154 Handle<Code> ic = | 2218 Handle<Code> ic = |
2155 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 2219 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
2156 __ Call(ic, mode, expr->id()); | 2220 CallIC(ic, mode, expr->id()); |
2157 RecordJSReturnSite(expr); | 2221 RecordJSReturnSite(expr); |
2158 // Restore context register. | 2222 // Restore context register. |
2159 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2223 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2160 context()->Plug(r0); | 2224 context()->Plug(r0); |
2161 } | 2225 } |
2162 | 2226 |
2163 | 2227 |
2164 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 2228 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
2165 Expression* key) { | 2229 Expression* key) { |
2166 // Load the key. | 2230 // Load the key. |
(...skipping 12 matching lines...) Expand all Loading... |
2179 for (int i = 0; i < arg_count; i++) { | 2243 for (int i = 0; i < arg_count; i++) { |
2180 VisitForStackValue(args->at(i)); | 2244 VisitForStackValue(args->at(i)); |
2181 } | 2245 } |
2182 } | 2246 } |
2183 // Record source position for debugger. | 2247 // Record source position for debugger. |
2184 SetSourcePosition(expr->position()); | 2248 SetSourcePosition(expr->position()); |
2185 // Call the IC initialization code. | 2249 // Call the IC initialization code. |
2186 Handle<Code> ic = | 2250 Handle<Code> ic = |
2187 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); | 2251 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); |
2188 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. | 2252 __ ldr(r2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. |
2189 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 2253 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
2190 RecordJSReturnSite(expr); | 2254 RecordJSReturnSite(expr); |
2191 // Restore context register. | 2255 // Restore context register. |
2192 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2256 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2193 context()->DropAndPlug(1, r0); // Drop the key still on the stack. | 2257 context()->DropAndPlug(1, r0); // Drop the key still on the stack. |
2194 } | 2258 } |
2195 | 2259 |
2196 | 2260 |
2197 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { | 2261 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { |
2198 // Code common for calls using the call stub. | 2262 // Code common for calls using the call stub. |
2199 ZoneList<Expression*>* args = expr->arguments(); | 2263 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++) { | 3840 for (int i = 0; i < arg_count; i++) { |
3777 VisitForStackValue(args->at(i)); | 3841 VisitForStackValue(args->at(i)); |
3778 } | 3842 } |
3779 | 3843 |
3780 if (expr->is_jsruntime()) { | 3844 if (expr->is_jsruntime()) { |
3781 // Call the JS runtime function. | 3845 // Call the JS runtime function. |
3782 __ mov(r2, Operand(expr->name())); | 3846 __ mov(r2, Operand(expr->name())); |
3783 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3847 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
3784 Handle<Code> ic = | 3848 Handle<Code> ic = |
3785 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); | 3849 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); |
3786 __ Call(ic, mode, expr->id()); | 3850 CallIC(ic, mode, expr->id()); |
3787 // Restore context register. | 3851 // Restore context register. |
3788 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3852 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
3789 } else { | 3853 } else { |
3790 // Call the C runtime function. | 3854 // Call the C runtime function. |
3791 __ CallRuntime(expr->function(), arg_count); | 3855 __ CallRuntime(expr->function(), arg_count); |
3792 } | 3856 } |
3793 context()->Plug(r0); | 3857 context()->Plug(r0); |
3794 } | 3858 } |
3795 | 3859 |
3796 | 3860 |
(...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... | 3995 // TODO(svenpanne): Allowing format strings in Comment would be nice here... |
3932 Comment cmt(masm_, comment); | 3996 Comment cmt(masm_, comment); |
3933 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); | 3997 bool can_overwrite = expr->expression()->ResultOverwriteAllowed(); |
3934 UnaryOverwriteMode overwrite = | 3998 UnaryOverwriteMode overwrite = |
3935 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; | 3999 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; |
3936 UnaryOpStub stub(expr->op(), overwrite); | 4000 UnaryOpStub stub(expr->op(), overwrite); |
3937 // UnaryOpStub expects the argument to be in the | 4001 // UnaryOpStub expects the argument to be in the |
3938 // accumulator register r0. | 4002 // accumulator register r0. |
3939 VisitForAccumulatorValue(expr->expression()); | 4003 VisitForAccumulatorValue(expr->expression()); |
3940 SetSourcePosition(expr->position()); | 4004 SetSourcePosition(expr->position()); |
3941 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); | 4005 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); |
3942 context()->Plug(r0); | 4006 context()->Plug(r0); |
3943 } | 4007 } |
3944 | 4008 |
3945 | 4009 |
3946 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { | 4010 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
3947 Comment cmnt(masm_, "[ CountOperation"); | 4011 Comment cmnt(masm_, "[ CountOperation"); |
3948 SetSourcePosition(expr->position()); | 4012 SetSourcePosition(expr->position()); |
3949 | 4013 |
3950 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' | 4014 // Invalid left-hand sides are rewritten to have a 'throw ReferenceError' |
3951 // as the left-hand side. | 4015 // as the left-hand side. |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4042 __ bind(&stub_call); | 4106 __ bind(&stub_call); |
4043 // Call stub. Undo operation first. | 4107 // Call stub. Undo operation first. |
4044 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); | 4108 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); |
4045 } | 4109 } |
4046 __ mov(r1, Operand(Smi::FromInt(count_value))); | 4110 __ mov(r1, Operand(Smi::FromInt(count_value))); |
4047 | 4111 |
4048 // Record position before stub call. | 4112 // Record position before stub call. |
4049 SetSourcePosition(expr->position()); | 4113 SetSourcePosition(expr->position()); |
4050 | 4114 |
4051 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 4115 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
4052 __ Call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); | 4116 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId()); |
4053 patch_site.EmitPatchInfo(); | 4117 patch_site.EmitPatchInfo(); |
4054 __ bind(&done); | 4118 __ bind(&done); |
4055 | 4119 |
4056 // Store the value returned in r0. | 4120 // Store the value returned in r0. |
4057 switch (assign_type) { | 4121 switch (assign_type) { |
4058 case VARIABLE: | 4122 case VARIABLE: |
4059 if (expr->is_postfix()) { | 4123 if (expr->is_postfix()) { |
4060 { EffectContext context(this); | 4124 { EffectContext context(this); |
4061 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 4125 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
4062 Token::ASSIGN); | 4126 Token::ASSIGN); |
(...skipping 11 matching lines...) Expand all Loading... |
4074 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4138 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4075 context()->Plug(r0); | 4139 context()->Plug(r0); |
4076 } | 4140 } |
4077 break; | 4141 break; |
4078 case NAMED_PROPERTY: { | 4142 case NAMED_PROPERTY: { |
4079 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 4143 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
4080 __ pop(r1); | 4144 __ pop(r1); |
4081 Handle<Code> ic = is_classic_mode() | 4145 Handle<Code> ic = is_classic_mode() |
4082 ? isolate()->builtins()->StoreIC_Initialize() | 4146 ? isolate()->builtins()->StoreIC_Initialize() |
4083 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 4147 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
4084 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4148 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4085 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4149 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4086 if (expr->is_postfix()) { | 4150 if (expr->is_postfix()) { |
4087 if (!context()->IsEffect()) { | 4151 if (!context()->IsEffect()) { |
4088 context()->PlugTOS(); | 4152 context()->PlugTOS(); |
4089 } | 4153 } |
4090 } else { | 4154 } else { |
4091 context()->Plug(r0); | 4155 context()->Plug(r0); |
4092 } | 4156 } |
4093 break; | 4157 break; |
4094 } | 4158 } |
4095 case KEYED_PROPERTY: { | 4159 case KEYED_PROPERTY: { |
4096 __ pop(r1); // Key. | 4160 __ pop(r1); // Key. |
4097 __ pop(r2); // Receiver. | 4161 __ pop(r2); // Receiver. |
4098 Handle<Code> ic = is_classic_mode() | 4162 Handle<Code> ic = is_classic_mode() |
4099 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4163 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
4100 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4164 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
4101 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4165 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4102 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4166 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4103 if (expr->is_postfix()) { | 4167 if (expr->is_postfix()) { |
4104 if (!context()->IsEffect()) { | 4168 if (!context()->IsEffect()) { |
4105 context()->PlugTOS(); | 4169 context()->PlugTOS(); |
4106 } | 4170 } |
4107 } else { | 4171 } else { |
4108 context()->Plug(r0); | 4172 context()->Plug(r0); |
4109 } | 4173 } |
4110 break; | 4174 break; |
4111 } | 4175 } |
4112 } | 4176 } |
4113 } | 4177 } |
4114 | 4178 |
4115 | 4179 |
4116 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { | 4180 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { |
4117 ASSERT(!context()->IsEffect()); | 4181 ASSERT(!context()->IsEffect()); |
4118 ASSERT(!context()->IsTest()); | 4182 ASSERT(!context()->IsTest()); |
4119 VariableProxy* proxy = expr->AsVariableProxy(); | 4183 VariableProxy* proxy = expr->AsVariableProxy(); |
4120 if (proxy != NULL && proxy->var()->IsUnallocated()) { | 4184 if (proxy != NULL && proxy->var()->IsUnallocated()) { |
4121 Comment cmnt(masm_, "Global variable"); | 4185 Comment cmnt(masm_, "Global variable"); |
4122 __ ldr(r0, GlobalObjectOperand()); | 4186 __ ldr(r0, GlobalObjectOperand()); |
4123 __ mov(r2, Operand(proxy->name())); | 4187 __ mov(r2, Operand(proxy->name())); |
4124 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 4188 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
4125 // Use a regular load, not a contextual load, to avoid a reference | 4189 // Use a regular load, not a contextual load, to avoid a reference |
4126 // error. | 4190 // error. |
4127 __ Call(ic); | 4191 CallIC(ic); |
4128 PrepareForBailout(expr, TOS_REG); | 4192 PrepareForBailout(expr, TOS_REG); |
4129 context()->Plug(r0); | 4193 context()->Plug(r0); |
4130 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { | 4194 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { |
4131 Label done, slow; | 4195 Label done, slow; |
4132 | 4196 |
4133 // Generate code for loading from variables potentially shadowed | 4197 // Generate code for loading from variables potentially shadowed |
4134 // by eval-introduced variables. | 4198 // by eval-introduced variables. |
4135 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); | 4199 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); |
4136 | 4200 |
4137 __ bind(&slow); | 4201 __ bind(&slow); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4300 __ orr(r2, r0, Operand(r1)); | 4364 __ orr(r2, r0, Operand(r1)); |
4301 patch_site.EmitJumpIfNotSmi(r2, &slow_case); | 4365 patch_site.EmitJumpIfNotSmi(r2, &slow_case); |
4302 __ cmp(r1, r0); | 4366 __ cmp(r1, r0); |
4303 Split(cond, if_true, if_false, NULL); | 4367 Split(cond, if_true, if_false, NULL); |
4304 __ bind(&slow_case); | 4368 __ bind(&slow_case); |
4305 } | 4369 } |
4306 | 4370 |
4307 // Record position and call the compare IC. | 4371 // Record position and call the compare IC. |
4308 SetSourcePosition(expr->position()); | 4372 SetSourcePosition(expr->position()); |
4309 Handle<Code> ic = CompareIC::GetUninitialized(op); | 4373 Handle<Code> ic = CompareIC::GetUninitialized(op); |
4310 __ Call(ic, RelocInfo::CODE_TARGET, expr->id()); | 4374 CallIC(ic, RelocInfo::CODE_TARGET, expr->id()); |
4311 patch_site.EmitPatchInfo(); | 4375 patch_site.EmitPatchInfo(); |
4312 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4376 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4313 __ cmp(r0, Operand(0)); | 4377 __ cmp(r0, Operand(0)); |
4314 Split(cond, if_true, if_false, fall_through); | 4378 Split(cond, if_true, if_false, fall_through); |
4315 } | 4379 } |
4316 } | 4380 } |
4317 | 4381 |
4318 // Convert the result of the comparison into one expected for this | 4382 // Convert the result of the comparison into one expected for this |
4319 // expression's context. | 4383 // expression's context. |
4320 context()->Plug(if_true, if_false); | 4384 context()->Plug(if_true, if_false); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4462 *context_length = 0; | 4526 *context_length = 0; |
4463 return previous_; | 4527 return previous_; |
4464 } | 4528 } |
4465 | 4529 |
4466 | 4530 |
4467 #undef __ | 4531 #undef __ |
4468 | 4532 |
4469 } } // namespace v8::internal | 4533 } } // namespace v8::internal |
4470 | 4534 |
4471 #endif // V8_TARGET_ARCH_ARM | 4535 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |