Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/mips/full-codegen-mips.cc

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

Powered by Google App Engine
This is Rietveld 408576698