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

Side by Side Diff: src/codegen-arm.cc

Issue 1930: Adapt to new calling convention on ARM. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « src/builtins-ia32.cc ('k') | src/disasm-arm.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 } 195 }
196 196
197 static MemOperand ContextOperand(Register context, int index) { 197 static MemOperand ContextOperand(Register context, int index) {
198 return MemOperand(context, Context::SlotOffset(index)); 198 return MemOperand(context, Context::SlotOffset(index));
199 } 199 }
200 200
201 static MemOperand ParameterOperand(Scope* scope, int index) { 201 static MemOperand ParameterOperand(Scope* scope, int index) {
202 // index -2 corresponds to the activated closure, -1 corresponds 202 // index -2 corresponds to the activated closure, -1 corresponds
203 // to the receiver 203 // to the receiver
204 ASSERT(-2 <= index && index < scope->num_parameters()); 204 ASSERT(-2 <= index && index < scope->num_parameters());
205 int offset = JavaScriptFrameConstants::kParam0Offset - index * kPointerSize; 205 int offset = (1 + scope->num_parameters() - index) * kPointerSize;
206 return MemOperand(pp, offset); 206 return MemOperand(fp, offset);
207 } 207 }
208 208
209 MemOperand ParameterOperand(int index) const { 209 MemOperand ParameterOperand(int index) const {
210 return ParameterOperand(scope_, index); 210 return ParameterOperand(scope_, index);
211 } 211 }
212 212
213 MemOperand FunctionOperand() const { return ParameterOperand(-2); } 213 MemOperand FunctionOperand() const {
214 return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset);
215 }
214 216
215 static MemOperand SlotOperand(MacroAssembler* masm, 217 static MemOperand SlotOperand(MacroAssembler* masm,
216 Scope* scope, 218 Scope* scope,
217 Slot* slot, 219 Slot* slot,
218 Register tmp); 220 Register tmp);
219 221
220 MemOperand SlotOperand(Slot* slot, Register tmp) { 222 MemOperand SlotOperand(Slot* slot, Register tmp) {
221 return SlotOperand(masm_, scope_, slot, tmp); 223 return SlotOperand(masm_, scope_, slot, tmp);
222 } 224 }
223 225
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 300
299 // Node visitors 301 // Node visitors
300 #define DEF_VISIT(type) \ 302 #define DEF_VISIT(type) \
301 virtual void Visit##type(type* node); 303 virtual void Visit##type(type* node);
302 NODE_LIST(DEF_VISIT) 304 NODE_LIST(DEF_VISIT)
303 #undef DEF_VISIT 305 #undef DEF_VISIT
304 306
305 void RecordStatementPosition(Node* node); 307 void RecordStatementPosition(Node* node);
306 308
307 // Activation frames 309 // Activation frames
308 void EnterJSFrame(int argc); // preserves r1 310 void EnterJSFrame();
309 void ExitJSFrame(ExitJSFlag flag = RETURN); // preserves r0-r2 311 void ExitJSFrame();
310 312
311 virtual void GenerateShiftDownAndTailCall(ZoneList<Expression*>* args); 313 virtual void GenerateShiftDownAndTailCall(ZoneList<Expression*>* args);
312 virtual void GenerateSetThisFunction(ZoneList<Expression*>* args); 314 virtual void GenerateSetThisFunction(ZoneList<Expression*>* args);
313 virtual void GenerateGetThisFunction(ZoneList<Expression*>* args); 315 virtual void GenerateGetThisFunction(ZoneList<Expression*>* args);
314 virtual void GenerateSetThis(ZoneList<Expression*>* args); 316 virtual void GenerateSetThis(ZoneList<Expression*>* args);
315 virtual void GenerateGetArgumentsLength(ZoneList<Expression*>* args); 317 virtual void GenerateGetArgumentsLength(ZoneList<Expression*>* args);
316 virtual void GenerateSetArgumentsLength(ZoneList<Expression*>* args); 318 virtual void GenerateSetArgumentsLength(ZoneList<Expression*>* args);
317 virtual void GenerateTailCallWithArguments(ZoneList<Expression*>* args); 319 virtual void GenerateTailCallWithArguments(ZoneList<Expression*>* args);
318 virtual void GenerateSetArgument(ZoneList<Expression*>* args); 320 virtual void GenerateSetArgument(ZoneList<Expression*>* args);
319 virtual void GenerateSquashFrame(ZoneList<Expression*>* args); 321 virtual void GenerateSquashFrame(ZoneList<Expression*>* args);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 463
462 // Entry 464 // Entry
463 // stack: function, receiver, arguments, return address 465 // stack: function, receiver, arguments, return address
464 // r0: number of arguments 466 // r0: number of arguments
465 // sp: stack pointer 467 // sp: stack pointer
466 // fp: frame pointer 468 // fp: frame pointer
467 // pp: caller's parameter pointer 469 // pp: caller's parameter pointer
468 // cp: callee's context 470 // cp: callee's context
469 471
470 { Comment cmnt(masm_, "[ enter JS frame"); 472 { Comment cmnt(masm_, "[ enter JS frame");
471 EnterJSFrame(scope->num_parameters()); 473 EnterJSFrame();
472 } 474 }
473 // tos: code slot 475 // tos: code slot
474 #ifdef DEBUG 476 #ifdef DEBUG
475 if (strlen(FLAG_stop_at) > 0 && 477 if (strlen(FLAG_stop_at) > 0 &&
476 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 478 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
477 __ stop("stop-at"); 479 __ stop("stop-at");
478 } 480 }
479 #endif 481 #endif
480 482
481 // Allocate space for locals and initialize them. 483 // Allocate space for locals and initialize them.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 // passed to the parameter that needs to be copied. This is a rare 521 // passed to the parameter that needs to be copied. This is a rare
520 // case so we don't check for it, instead we rely on the copying 522 // case so we don't check for it, instead we rely on the copying
521 // order: such a parameter is copied repeatedly into the same 523 // order: such a parameter is copied repeatedly into the same
522 // context location and thus the last value is what is seen inside 524 // context location and thus the last value is what is seen inside
523 // the function. 525 // the function.
524 for (int i = 0; i < scope->num_parameters(); i++) { 526 for (int i = 0; i < scope->num_parameters(); i++) {
525 Variable* par = scope->parameter(i); 527 Variable* par = scope->parameter(i);
526 Slot* slot = par->slot(); 528 Slot* slot = par->slot();
527 if (slot != NULL && slot->type() == Slot::CONTEXT) { 529 if (slot != NULL && slot->type() == Slot::CONTEXT) {
528 ASSERT(!scope->is_global_scope()); // no parameters in global scope 530 ASSERT(!scope->is_global_scope()); // no parameters in global scope
529 int parameter_offset = 531 __ ldr(r1, ParameterOperand(i));
530 JavaScriptFrameConstants::kParam0Offset - i * kPointerSize;
531 __ ldr(r1, MemOperand(pp, parameter_offset));
532 // Loads r2 with context; used below in RecordWrite. 532 // Loads r2 with context; used below in RecordWrite.
533 __ str(r1, SlotOperand(slot, r2)); 533 __ str(r1, SlotOperand(slot, r2));
534 // Load the offset into r3. 534 // Load the offset into r3.
535 int slot_offset = 535 int slot_offset =
536 FixedArray::kHeaderSize + slot->index() * kPointerSize; 536 FixedArray::kHeaderSize + slot->index() * kPointerSize;
537 __ mov(r3, Operand(slot_offset)); 537 __ mov(r3, Operand(slot_offset));
538 __ RecordWrite(r2, r3, r1); 538 __ RecordWrite(r2, r3, r1);
539 } 539 }
540 } 540 }
541 } 541 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 __ mov(r0, Operand(Factory::undefined_value())); 622 __ mov(r0, Operand(Factory::undefined_value()));
623 623
624 __ bind(&function_return_); 624 __ bind(&function_return_);
625 if (FLAG_trace) { 625 if (FLAG_trace) {
626 // Push the return value on the stack as the parameter. 626 // Push the return value on the stack as the parameter.
627 // Runtime::TraceExit returns the parameter as it is. 627 // Runtime::TraceExit returns the parameter as it is.
628 __ push(r0); 628 __ push(r0);
629 __ CallRuntime(Runtime::kTraceExit, 1); 629 __ CallRuntime(Runtime::kTraceExit, 1);
630 } 630 }
631 631
632 // Tear down the frame which will restore the caller's frame pointer and the
633 // link register.
632 ExitJSFrame(); 634 ExitJSFrame();
633 635
636 __ add(sp, sp, Operand((scope_->num_parameters() + 1) * kPointerSize));
637 __ mov(pc, lr);
638
634 // Code generation state must be reset. 639 // Code generation state must be reset.
635 scope_ = NULL; 640 scope_ = NULL;
636 ASSERT(!has_cc()); 641 ASSERT(!has_cc());
637 ASSERT(state_ == NULL); 642 ASSERT(state_ == NULL);
638 } 643 }
639 644
640 645
641 MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm, 646 MemOperand ArmCodeGenerator::SlotOperand(MacroAssembler* masm,
642 Scope* scope, 647 Scope* scope,
643 Slot* slot, 648 Slot* slot,
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 // hole' value and by doing so, end up calling this code. r2 may be 976 // hole' value and by doing so, end up calling this code. r2 may be
972 // loaded with context; used below in RecordWrite. 977 // loaded with context; used below in RecordWrite.
973 masm->pop(r0); 978 masm->pop(r0);
974 masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2)); 979 masm->str(r0, ArmCodeGenerator::SlotOperand(masm, scope, this, r2));
975 masm->push(r0); 980 masm->push(r0);
976 981
977 if (type() == Slot::CONTEXT) { 982 if (type() == Slot::CONTEXT) {
978 // Skip write barrier if the written value is a smi. 983 // Skip write barrier if the written value is a smi.
979 masm->tst(r0, Operand(kSmiTagMask)); 984 masm->tst(r0, Operand(kSmiTagMask));
980 masm->b(eq, &exit); 985 masm->b(eq, &exit);
986 may_skip_write = true;
981 // r2 is loaded with context when calling SlotOperand above. 987 // r2 is loaded with context when calling SlotOperand above.
982 int offset = FixedArray::kHeaderSize + index() * kPointerSize; 988 int offset = FixedArray::kHeaderSize + index() * kPointerSize;
983 masm->mov(r3, Operand(offset)); 989 masm->mov(r3, Operand(offset));
984 masm->RecordWrite(r2, r3, r1); 990 masm->RecordWrite(r2, r3, r1);
985 } 991 }
986 // If we definitely did not jump over the assignment, we do not need to 992 // If we definitely did not jump over the assignment, we do not need to
987 // bind the exit label. Doing so can defeat peephole optimization. 993 // bind the exit label. Doing so can defeat peephole optimization.
988 if (may_skip_write) masm->bind(&exit); 994 if (may_skip_write) masm->bind(&exit);
989 } 995 }
990 } 996 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 // go slow-path in case of non-smi operands 1280 // go slow-path in case of non-smi operands
1275 ASSERT(kSmiTag == 0); // adjust code below 1281 ASSERT(kSmiTag == 0); // adjust code below
1276 __ tst(r2, Operand(kSmiTagMask)); 1282 __ tst(r2, Operand(kSmiTagMask));
1277 __ b(eq, &exit); 1283 __ b(eq, &exit);
1278 // slow path 1284 // slow path
1279 __ bind(&slow); 1285 __ bind(&slow);
1280 __ sub(r0, r0, Operand(r1)); // revert optimistic add 1286 __ sub(r0, r0, Operand(r1)); // revert optimistic add
1281 __ push(r1); 1287 __ push(r1);
1282 __ push(r0); 1288 __ push(r0);
1283 __ mov(r0, Operand(1)); // set number of arguments 1289 __ mov(r0, Operand(1)); // set number of arguments
1284 __ InvokeBuiltin("ADD", 1, JUMP_JS); 1290 __ InvokeBuiltin(Builtins::ADD, JUMP_JS);
1285 // done 1291 // done
1286 __ bind(&exit); 1292 __ bind(&exit);
1287 break; 1293 break;
1288 } 1294 }
1289 1295
1290 case Token::SUB: { 1296 case Token::SUB: {
1291 Label slow, exit; 1297 Label slow, exit;
1292 // fast path 1298 // fast path
1293 __ orr(r2, r1, Operand(r0)); // r2 = x | y; 1299 __ orr(r2, r1, Operand(r0)); // r2 = x | y;
1294 __ sub(r3, r1, Operand(r0), SetCC); // subtract y optimistically 1300 __ sub(r3, r1, Operand(r0), SetCC); // subtract y optimistically
1295 // go slow-path in case of overflow 1301 // go slow-path in case of overflow
1296 __ b(vs, &slow); 1302 __ b(vs, &slow);
1297 // go slow-path in case of non-smi operands 1303 // go slow-path in case of non-smi operands
1298 ASSERT(kSmiTag == 0); // adjust code below 1304 ASSERT(kSmiTag == 0); // adjust code below
1299 __ tst(r2, Operand(kSmiTagMask)); 1305 __ tst(r2, Operand(kSmiTagMask));
1300 __ mov(r0, Operand(r3), LeaveCC, eq); // conditionally set r0 to result 1306 __ mov(r0, Operand(r3), LeaveCC, eq); // conditionally set r0 to result
1301 __ b(eq, &exit); 1307 __ b(eq, &exit);
1302 // slow path 1308 // slow path
1303 __ bind(&slow); 1309 __ bind(&slow);
1304 __ push(r1); 1310 __ push(r1);
1305 __ push(r0); 1311 __ push(r0);
1306 __ mov(r0, Operand(1)); // set number of arguments 1312 __ mov(r0, Operand(1)); // set number of arguments
1307 __ InvokeBuiltin("SUB", 1, JUMP_JS); 1313 __ InvokeBuiltin(Builtins::SUB, JUMP_JS);
1308 // done 1314 // done
1309 __ bind(&exit); 1315 __ bind(&exit);
1310 break; 1316 break;
1311 } 1317 }
1312 1318
1313 case Token::MUL: { 1319 case Token::MUL: {
1314 Label slow, exit; 1320 Label slow, exit;
1315 // tag check 1321 // tag check
1316 __ orr(r2, r1, Operand(r0)); // r2 = x | y; 1322 __ orr(r2, r1, Operand(r0)); // r2 = x | y;
1317 ASSERT(kSmiTag == 0); // adjust code below 1323 ASSERT(kSmiTag == 0); // adjust code below
1318 __ tst(r2, Operand(kSmiTagMask)); 1324 __ tst(r2, Operand(kSmiTagMask));
1319 __ b(ne, &slow); 1325 __ b(ne, &slow);
1320 // remove tag from one operand (but keep sign), so that result is smi 1326 // remove tag from one operand (but keep sign), so that result is smi
1321 __ mov(ip, Operand(r0, ASR, kSmiTagSize)); 1327 __ mov(ip, Operand(r0, ASR, kSmiTagSize));
1322 // do multiplication 1328 // do multiplication
1323 __ smull(r3, r2, r1, ip); // r3 = lower 32 bits of ip*r1 1329 __ smull(r3, r2, r1, ip); // r3 = lower 32 bits of ip*r1
1324 // go slow on overflows (overflow bit is not set) 1330 // go slow on overflows (overflow bit is not set)
1325 __ mov(ip, Operand(r3, ASR, 31)); 1331 __ mov(ip, Operand(r3, ASR, 31));
1326 __ cmp(ip, Operand(r2)); // no overflow if higher 33 bits are identical 1332 __ cmp(ip, Operand(r2)); // no overflow if higher 33 bits are identical
1327 __ b(ne, &slow); 1333 __ b(ne, &slow);
1328 // go slow on zero result to handle -0 1334 // go slow on zero result to handle -0
1329 __ tst(r3, Operand(r3)); 1335 __ tst(r3, Operand(r3));
1330 __ mov(r0, Operand(r3), LeaveCC, ne); 1336 __ mov(r0, Operand(r3), LeaveCC, ne);
1331 __ b(ne, &exit); 1337 __ b(ne, &exit);
1332 // slow case 1338 // slow case
1333 __ bind(&slow); 1339 __ bind(&slow);
1334 __ push(r1); 1340 __ push(r1);
1335 __ push(r0); 1341 __ push(r0);
1336 __ mov(r0, Operand(1)); // set number of arguments 1342 __ mov(r0, Operand(1)); // set number of arguments
1337 __ InvokeBuiltin("MUL", 1, JUMP_JS); 1343 __ InvokeBuiltin(Builtins::MUL, JUMP_JS);
1338 // done 1344 // done
1339 __ bind(&exit); 1345 __ bind(&exit);
1340 break; 1346 break;
1341 } 1347 }
1342 1348
1343 case Token::BIT_OR: 1349 case Token::BIT_OR:
1344 case Token::BIT_AND: 1350 case Token::BIT_AND:
1345 case Token::BIT_XOR: { 1351 case Token::BIT_XOR: {
1346 Label slow, exit; 1352 Label slow, exit;
1347 // tag check 1353 // tag check
1348 __ orr(r2, r1, Operand(r0)); // r2 = x | y; 1354 __ orr(r2, r1, Operand(r0)); // r2 = x | y;
1349 ASSERT(kSmiTag == 0); // adjust code below 1355 ASSERT(kSmiTag == 0); // adjust code below
1350 __ tst(r2, Operand(kSmiTagMask)); 1356 __ tst(r2, Operand(kSmiTagMask));
1351 __ b(ne, &slow); 1357 __ b(ne, &slow);
1352 switch (op_) { 1358 switch (op_) {
1353 case Token::BIT_OR: __ orr(r0, r0, Operand(r1)); break; 1359 case Token::BIT_OR: __ orr(r0, r0, Operand(r1)); break;
1354 case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break; 1360 case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break;
1355 case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break; 1361 case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
1356 default: UNREACHABLE(); 1362 default: UNREACHABLE();
1357 } 1363 }
1358 __ b(&exit); 1364 __ b(&exit);
1359 __ bind(&slow); 1365 __ bind(&slow);
1360 __ push(r1); // restore stack 1366 __ push(r1); // restore stack
1361 __ push(r0); 1367 __ push(r0);
1362 __ mov(r0, Operand(1)); // 1 argument (not counting receiver). 1368 __ mov(r0, Operand(1)); // 1 argument (not counting receiver).
1363 switch (op_) { 1369 switch (op_) {
1364 case Token::BIT_OR: __ InvokeBuiltin("BIT_OR", 1, JUMP_JS); break; 1370 case Token::BIT_OR:
1365 case Token::BIT_AND: __ InvokeBuiltin("BIT_AND", 1, JUMP_JS); break; 1371 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS);
1366 case Token::BIT_XOR: __ InvokeBuiltin("BIT_XOR", 1, JUMP_JS); break; 1372 break;
1367 default: UNREACHABLE(); 1373 case Token::BIT_AND:
1374 __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS);
1375 break;
1376 case Token::BIT_XOR:
1377 __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS);
1378 break;
1379 default:
1380 UNREACHABLE();
1368 } 1381 }
1369 __ bind(&exit); 1382 __ bind(&exit);
1370 break; 1383 break;
1371 } 1384 }
1372 1385
1373 case Token::SHL: 1386 case Token::SHL:
1374 case Token::SHR: 1387 case Token::SHR:
1375 case Token::SAR: { 1388 case Token::SAR: {
1376 Label slow, exit; 1389 Label slow, exit;
1377 // tag check 1390 // tag check
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 // tag result and store it in r0 1428 // tag result and store it in r0
1416 ASSERT(kSmiTag == 0); // adjust code below 1429 ASSERT(kSmiTag == 0); // adjust code below
1417 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 1430 __ mov(r0, Operand(r3, LSL, kSmiTagSize));
1418 __ b(&exit); 1431 __ b(&exit);
1419 // slow case 1432 // slow case
1420 __ bind(&slow); 1433 __ bind(&slow);
1421 __ push(r1); // restore stack 1434 __ push(r1); // restore stack
1422 __ push(r0); 1435 __ push(r0);
1423 __ mov(r0, Operand(1)); // 1 argument (not counting receiver). 1436 __ mov(r0, Operand(1)); // 1 argument (not counting receiver).
1424 switch (op_) { 1437 switch (op_) {
1425 case Token::SAR: __ InvokeBuiltin("SAR", 1, JUMP_JS); break; 1438 case Token::SAR: __ InvokeBuiltin(Builtins::SAR, JUMP_JS); break;
1426 case Token::SHR: __ InvokeBuiltin("SHR", 1, JUMP_JS); break; 1439 case Token::SHR: __ InvokeBuiltin(Builtins::SHR, JUMP_JS); break;
1427 case Token::SHL: __ InvokeBuiltin("SHL", 1, JUMP_JS); break; 1440 case Token::SHL: __ InvokeBuiltin(Builtins::SHL, JUMP_JS); break;
1428 default: UNREACHABLE(); 1441 default: UNREACHABLE();
1429 } 1442 }
1430 __ bind(&exit); 1443 __ bind(&exit);
1431 break; 1444 break;
1432 } 1445 }
1433 1446
1434 default: UNREACHABLE(); 1447 default: UNREACHABLE();
1435 } 1448 }
1436 __ Ret(); 1449 __ Ret();
1437 } 1450 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 1486
1474 // If result is a smi we are done. 1487 // If result is a smi we are done.
1475 __ tst(r1, Operand(kSmiTagMask)); 1488 __ tst(r1, Operand(kSmiTagMask));
1476 __ mov(r0, Operand(r1), LeaveCC, eq); // conditionally set r0 to result 1489 __ mov(r0, Operand(r1), LeaveCC, eq); // conditionally set r0 to result
1477 __ b(eq, &done); 1490 __ b(eq, &done);
1478 1491
1479 // Enter runtime system. 1492 // Enter runtime system.
1480 __ bind(&slow); 1493 __ bind(&slow);
1481 __ push(r0); 1494 __ push(r0);
1482 __ mov(r0, Operand(0)); // set number of arguments 1495 __ mov(r0, Operand(0)); // set number of arguments
1483 __ InvokeBuiltin("UNARY_MINUS", 0, JUMP_JS); 1496 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS);
1484 1497
1485 __ bind(&done); 1498 __ bind(&done);
1486 masm->StubReturn(1); 1499 masm->StubReturn(1);
1487 } 1500 }
1488 1501
1489 1502
1490 class InvokeBuiltinStub : public CodeStub { 1503 class InvokeBuiltinStub : public CodeStub {
1491 public: 1504 public:
1492 enum Kind { Inc, Dec, ToNumber }; 1505 enum Kind { Inc, Dec, ToNumber };
1493 InvokeBuiltinStub(Kind kind, int argc) : kind_(kind), argc_(argc) { } 1506 InvokeBuiltinStub(Kind kind, int argc) : kind_(kind), argc_(argc) { }
(...skipping 15 matching lines...) Expand all
1509 argc_); 1522 argc_);
1510 } 1523 }
1511 #endif 1524 #endif
1512 }; 1525 };
1513 1526
1514 1527
1515 void InvokeBuiltinStub::Generate(MacroAssembler* masm) { 1528 void InvokeBuiltinStub::Generate(MacroAssembler* masm) {
1516 __ push(r0); 1529 __ push(r0);
1517 __ mov(r0, Operand(0)); // set number of arguments 1530 __ mov(r0, Operand(0)); // set number of arguments
1518 switch (kind_) { 1531 switch (kind_) {
1519 case ToNumber: __ InvokeBuiltin("TO_NUMBER", 0, JUMP_JS); break; 1532 case ToNumber: __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_JS); break;
1520 case Inc: __ InvokeBuiltin("INC", 0, JUMP_JS); break; 1533 case Inc: __ InvokeBuiltin(Builtins::INC, JUMP_JS); break;
1521 case Dec: __ InvokeBuiltin("DEC", 0, JUMP_JS); break; 1534 case Dec: __ InvokeBuiltin(Builtins::DEC, JUMP_JS); break;
1522 default: UNREACHABLE(); 1535 default: UNREACHABLE();
1523 } 1536 }
1524 masm->StubReturn(argc_); 1537 masm->StubReturn(argc_);
1525 } 1538 }
1526 1539
1527 1540
1528 class JSExitStub : public CodeStub {
1529 public:
1530 enum Kind { Inc, Dec, ToNumber };
1531
1532 explicit JSExitStub(ExitJSFlag flag) : flag_(flag) { }
1533
1534 private:
1535 ExitJSFlag flag_;
1536
1537 Major MajorKey() { return JSExit; }
1538 int MinorKey() { return static_cast<int>(flag_); }
1539 void Generate(MacroAssembler* masm);
1540
1541 const char* GetName() { return "JSExitStub"; }
1542
1543 #ifdef DEBUG
1544 void Print() {
1545 PrintF("JSExitStub flag %d)\n", static_cast<int>(flag_));
1546 }
1547 #endif
1548 };
1549
1550
1551 void JSExitStub::Generate(MacroAssembler* masm) {
1552 __ ExitJSFrame(flag_);
1553 masm->StubReturn(1);
1554 }
1555
1556
1557
1558 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 1541 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
1559 // r0 holds exception 1542 // r0 holds exception
1560 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code 1543 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
1561 __ mov(r3, Operand(ExternalReference(Top::k_handler_address))); 1544 __ mov(r3, Operand(ExternalReference(Top::k_handler_address)));
1562 __ ldr(sp, MemOperand(r3)); 1545 __ ldr(sp, MemOperand(r3));
1563 __ pop(r2); // pop next in chain 1546 __ pop(r2); // pop next in chain
1564 __ str(r2, MemOperand(r3)); 1547 __ str(r2, MemOperand(r3));
1565 // restore parameter- and frame-pointer and pop state. 1548 // restore parameter- and frame-pointer and pop state.
1566 __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit()); 1549 __ ldm(ia_w, sp, r3.bit() | pp.bit() | fp.bit());
1567 // Before returning we restore the context from the frame pointer if not NULL. 1550 // Before returning we restore the context from the frame pointer if not NULL.
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1694 // Exit C frame and return 1677 // Exit C frame and return
1695 // r0:r1: result 1678 // r0:r1: result
1696 // sp: stack pointer 1679 // sp: stack pointer
1697 // fp: frame pointer 1680 // fp: frame pointer
1698 // pp: caller's parameter pointer pp (restored as C callee-saved) 1681 // pp: caller's parameter pointer pp (restored as C callee-saved)
1699 1682
1700 // Restore current context from top and clear it in debug mode. 1683 // Restore current context from top and clear it in debug mode.
1701 __ mov(r3, Operand(Top::context_address())); 1684 __ mov(r3, Operand(Top::context_address()));
1702 __ ldr(cp, MemOperand(r3)); 1685 __ ldr(cp, MemOperand(r3));
1703 __ mov(sp, Operand(fp)); // respect ABI stack constraint 1686 __ mov(sp, Operand(fp)); // respect ABI stack constraint
1704 __ ldm(ia, sp, pp.bit() | fp.bit() | sp.bit() | pc.bit()); 1687 __ ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
1705 1688
1706 // check if we should retry or throw exception 1689 // check if we should retry or throw exception
1707 Label retry; 1690 Label retry;
1708 __ bind(&failure_returned); 1691 __ bind(&failure_returned);
1709 ASSERT(Failure::RETRY_AFTER_GC == 0); 1692 ASSERT(Failure::RETRY_AFTER_GC == 0);
1710 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 1693 __ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
1711 __ b(eq, &retry); 1694 __ b(eq, &retry);
1712 1695
1713 Label continue_exception; 1696 Label continue_exception;
1714 // If the returned failure is EXCEPTION then promote Top::pending_exception(). 1697 // If the returned failure is EXCEPTION then promote Top::pending_exception().
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1748 // instead of a proper result. The builtin entry handles 1731 // instead of a proper result. The builtin entry handles
1749 // this by performing a garbage collection and retrying the 1732 // this by performing a garbage collection and retrying the
1750 // builtin once. 1733 // builtin once.
1751 1734
1752 // Enter C frame 1735 // Enter C frame
1753 // Compute parameter pointer before making changes and save it as ip register 1736 // Compute parameter pointer before making changes and save it as ip register
1754 // so that it is restored as sp register on exit, thereby popping the args. 1737 // so that it is restored as sp register on exit, thereby popping the args.
1755 // ip = sp + kPointerSize*args_len; 1738 // ip = sp + kPointerSize*args_len;
1756 __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); 1739 __ add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
1757 1740
1758 // all JS callee-saved are saved and traversed by GC; push in reverse order: 1741 // push in reverse order:
1759 // JS callee-saved, caller_pp, caller_fp, sp_on_exit (ip==pp), caller_pc 1742 // caller_fp, sp_on_exit, caller_pc
1760 __ stm(db_w, sp, pp.bit() | fp.bit() | ip.bit() | lr.bit()); 1743 __ stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
1761 __ mov(fp, Operand(sp)); // setup new frame pointer 1744 __ mov(fp, Operand(sp)); // setup new frame pointer
1762 1745
1763 // Store the current context in top. 1746 // Store the current context in top.
1764 __ mov(ip, Operand(Top::context_address())); 1747 __ mov(ip, Operand(ExternalReference(Top::k_context_address)));
1765 __ str(cp, MemOperand(ip)); 1748 __ str(cp, MemOperand(ip));
1766 1749
1767 // remember top frame 1750 // remember top frame
1768 __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); 1751 __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
1769 __ str(fp, MemOperand(ip)); 1752 __ str(fp, MemOperand(ip));
1770 1753
1771 // Push debug marker. 1754 // Push debug marker.
1772 __ mov(ip, Operand(is_debug_break ? 1 : 0)); 1755 __ mov(ip, Operand(is_debug_break ? 1 : 0));
1773 __ push(ip); 1756 __ push(ip);
1774 1757
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1831 // r1: function 1814 // r1: function
1832 // r2: receiver 1815 // r2: receiver
1833 // r3: argc 1816 // r3: argc
1834 // [sp+0]: argv 1817 // [sp+0]: argv
1835 1818
1836 Label invoke, exit; 1819 Label invoke, exit;
1837 1820
1838 // Called from C, so do not pop argc and args on exit (preserve sp) 1821 // Called from C, so do not pop argc and args on exit (preserve sp)
1839 // No need to save register-passed args 1822 // No need to save register-passed args
1840 // Save callee-saved registers (incl. cp, pp, and fp), sp, and lr 1823 // Save callee-saved registers (incl. cp, pp, and fp), sp, and lr
1841 __ mov(ip, Operand(sp)); 1824 __ stm(db_w, sp, kCalleeSaved | lr.bit());
1842 __ stm(db_w, sp, kCalleeSaved | ip.bit() | lr.bit());
1843
1844 // Setup frame pointer
1845 __ mov(fp, Operand(sp));
1846
1847 // Add constructor mark.
1848 __ mov(ip, Operand(is_construct ? 1 : 0));
1849 __ push(ip);
1850
1851 // Move arguments into registers expected by Builtins::JSEntryTrampoline
1852 // preserve r0-r3, set r4, r5-r7 may be clobbered
1853 1825
1854 // Get address of argv, see stm above. 1826 // Get address of argv, see stm above.
1855 __ add(r4, sp, Operand((kNumCalleeSaved + 3)*kPointerSize)); 1827 // r0: code entry
1828 // r1: function
1829 // r2: receiver
1830 // r3: argc
1831 __ add(r4, sp, Operand((kNumCalleeSaved + 1)*kPointerSize));
1856 __ ldr(r4, MemOperand(r4)); // argv 1832 __ ldr(r4, MemOperand(r4)); // argv
1857 1833
1858 // Save copies of the top frame descriptors on the stack. 1834 // Push a frame with special values setup to mark it as an entry frame.
1859 __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); 1835 // r0: code entry
1860 __ ldr(r6, MemOperand(ip)); 1836 // r1: function
1861 __ stm(db_w, sp, r6.bit()); 1837 // r2: receiver
1838 // r3: argc
1839 // r4: argv
1840 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
1841 __ mov(r8, Operand(-1)); // Push a bad frame pointer to fail if it is used.
1842 __ mov(r7, Operand(~ArgumentsAdaptorFrame::SENTINEL));
1843 __ mov(r6, Operand(Smi::FromInt(marker)));
1844 __ mov(r5, Operand(ExternalReference(Top::k_c_entry_fp_address)));
1845 __ ldr(r5, MemOperand(r5));
1846 __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | r8.bit());
1847
1848 // Setup frame pointer for the frame to be pushed.
1849 __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1862 1850
1863 // Call a faked try-block that does the invoke. 1851 // Call a faked try-block that does the invoke.
1864 __ bl(&invoke); 1852 __ bl(&invoke);
1865 1853
1866 // Caught exception: Store result (exception) in the pending 1854 // Caught exception: Store result (exception) in the pending
1867 // exception field in the JSEnv and return a failure sentinel. 1855 // exception field in the JSEnv and return a failure sentinel.
1856 // Coming in here the fp will be invalid because the PushTryHandler below
1857 // sets it to 0 to signal the existence of the JSEntry frame.
1868 __ mov(ip, Operand(Top::pending_exception_address())); 1858 __ mov(ip, Operand(Top::pending_exception_address()));
1869 __ str(r0, MemOperand(ip)); 1859 __ str(r0, MemOperand(ip));
1870 __ mov(r0, Operand(Handle<Failure>(Failure::Exception()))); 1860 __ mov(r0, Operand(Handle<Failure>(Failure::Exception())));
1871 __ b(&exit); 1861 __ b(&exit);
1872 1862
1873 // Invoke: Link this frame into the handler chain. 1863 // Invoke: Link this frame into the handler chain.
1874 __ bind(&invoke); 1864 __ bind(&invoke);
1875 // Must preserve r0-r3, r5-r7 are available. 1865 // Must preserve r0-r4, r5-r7 are available.
1876 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER); 1866 __ PushTryHandler(IN_JS_ENTRY, JS_ENTRY_HANDLER);
1877 // If an exception not caught by another handler occurs, this handler returns 1867 // If an exception not caught by another handler occurs, this handler returns
1878 // control to the code after the bl(&invoke) above, which restores all 1868 // control to the code after the bl(&invoke) above, which restores all
1879 // kCalleeSaved registers (including cp, pp and fp) to their saved values 1869 // kCalleeSaved registers (including cp, pp and fp) to their saved values
1880 // before returning a failure to C. 1870 // before returning a failure to C.
1881 1871
1882 // Clear any pending exceptions. 1872 // Clear any pending exceptions.
1883 __ mov(ip, Operand(ExternalReference::the_hole_value_location())); 1873 __ mov(ip, Operand(ExternalReference::the_hole_value_location()));
1884 __ ldr(r5, MemOperand(ip)); 1874 __ ldr(r5, MemOperand(ip));
1885 __ mov(ip, Operand(Top::pending_exception_address())); 1875 __ mov(ip, Operand(Top::pending_exception_address()));
(...skipping 27 matching lines...) Expand all
1913 // displacement since the current stack pointer (sp) points directly 1903 // displacement since the current stack pointer (sp) points directly
1914 // to the stack handler. 1904 // to the stack handler.
1915 __ ldr(r3, MemOperand(sp, StackHandlerConstants::kNextOffset)); 1905 __ ldr(r3, MemOperand(sp, StackHandlerConstants::kNextOffset));
1916 __ mov(ip, Operand(ExternalReference(Top::k_handler_address))); 1906 __ mov(ip, Operand(ExternalReference(Top::k_handler_address)));
1917 __ str(r3, MemOperand(ip)); 1907 __ str(r3, MemOperand(ip));
1918 // No need to restore registers 1908 // No need to restore registers
1919 __ add(sp, sp, Operand(StackHandlerConstants::kSize)); 1909 __ add(sp, sp, Operand(StackHandlerConstants::kSize));
1920 1910
1921 __ bind(&exit); // r0 holds result 1911 __ bind(&exit); // r0 holds result
1922 // Restore the top frame descriptors from the stack. 1912 // Restore the top frame descriptors from the stack.
1923 __ ldm(ia_w, sp, r3.bit()); 1913 __ pop(r3);
1924 __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); 1914 __ mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
1925 __ str(r3, MemOperand(ip)); 1915 __ str(r3, MemOperand(ip));
1926 1916
1927 // Remove constructor mark. 1917 // Reset the stack to the callee saved registers.
1928 __ pop(); 1918 __ add(sp, sp, Operand(-EntryFrameConstants::kCallerFPOffset));
1929 1919
1930 // Restore callee-saved registers, sp, and return. 1920 // Restore callee-saved registers and return.
1931 #ifdef DEBUG 1921 #ifdef DEBUG
1932 if (FLAG_debug_code) __ mov(lr, Operand(pc)); 1922 if (FLAG_debug_code) __ mov(lr, Operand(pc));
1933 #endif 1923 #endif
1934 __ ldm(ia, sp, kCalleeSaved | sp.bit() | pc.bit()); 1924 __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
1935 } 1925 }
1936 1926
1937 1927
1938 class ArgumentsAccessStub: public CodeStub { 1928 class ArgumentsAccessStub: public CodeStub {
1939 public: 1929 public:
1940 explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { } 1930 explicit ArgumentsAccessStub(bool is_length) : is_length_(is_length) { }
1941 1931
1942 private: 1932 private:
1943 bool is_length_; 1933 bool is_length_;
1944 1934
1945 Major MajorKey() { return ArgumentsAccess; } 1935 Major MajorKey() { return ArgumentsAccess; }
1946 int MinorKey() { return is_length_ ? 1 : 0; } 1936 int MinorKey() { return is_length_ ? 1 : 0; }
1947 void Generate(MacroAssembler* masm); 1937 void Generate(MacroAssembler* masm);
1948 1938
1949 const char* GetName() { return "ArgumentsAccessStub"; } 1939 const char* GetName() { return "ArgumentsAccessStub"; }
1950 1940
1951 #ifdef DEBUG 1941 #ifdef DEBUG
1952 void Print() { 1942 void Print() {
1953 PrintF("ArgumentsAccessStub (is_length %s)\n", 1943 PrintF("ArgumentsAccessStub (is_length %s)\n",
1954 is_length_ ? "true" : "false"); 1944 is_length_ ? "true" : "false");
1955 } 1945 }
1956 #endif 1946 #endif
1957 }; 1947 };
1958 1948
1959 1949
1960 void ArgumentsAccessStub::Generate(MacroAssembler* masm) { 1950 void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
1951 // ----------- S t a t e -------------
1952 // -- r0: formal number of parameters for the calling function
1953 // -- r1: key (if value access)
1954 // -- lr: return address
1955 // -----------------------------------
1956
1957 // Check that the key is a smi for non-length accesses.
1958 Label slow;
1959 if (!is_length_) {
1960 __ tst(r1, Operand(kSmiTagMask));
1961 __ b(ne, &slow);
1962 }
1963
1964 // Check if the calling frame is an arguments adaptor frame.
1965 // r0: formal number of parameters
1966 // r1: key (if access)
1967 Label adaptor;
1968 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
1969 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
1970 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));
1971 __ b(eq, &adaptor);
1972
1973 static const int kParamDisplacement =
1974 StandardFrameConstants::kCallerSPOffset - kPointerSize;
1975
1961 if (is_length_) { 1976 if (is_length_) {
1962 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset)); 1977 // Nothing to do: the formal length of parameters has been passed in r0
1963 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); 1978 // by the calling function.
1964 __ Ret();
1965 } else { 1979 } else {
1966 // Check that the key is a smi. 1980 // Check index against formal parameter count. Use unsigned comparison to
1967 Label slow; 1981 // get the negative check for free.
1968 __ tst(r0, Operand(kSmiTagMask)); 1982 // r0: formal number of parameters
1969 __ b(ne, &slow); 1983 // r1: index
1984 __ cmp(r1, r0);
1985 __ b(cs, &slow);
1970 1986
1971 // Get the actual number of arguments passed and do bounds 1987 // Read the argument from the current frame.
1972 // check. Use unsigned comparison to get negative check for free. 1988 __ sub(r3, r0, r1);
1973 __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset)); 1989 __ add(r3, fp, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
1974 __ cmp(r0, Operand(r1, LSL, kSmiTagSize)); 1990 __ ldr(r0, MemOperand(r3, kParamDisplacement));
1975 __ b(hs, &slow); 1991 }
1976 1992
1977 // Load the argument directly from the stack and return. 1993 // Return to the calling function.
1978 __ sub(r1, pp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1994 __ mov(pc, lr);
1979 __ ldr(r0, MemOperand(r1, JavaScriptFrameConstants::kParam0Offset));
1980 __ Ret();
1981 1995
1982 // Slow-case: Handle non-smi or out-of-bounds access to arguments 1996 // An arguments adaptor frame is present. Find the length or the actual
1983 // by calling the runtime system. 1997 // argument in the calling frame.
1998 // r0: formal number of parameters
1999 // r1: key
2000 // r2: adaptor frame pointer
2001 __ bind(&adaptor);
2002 // Read the arguments length from the adaptor frame. This is the result if
2003 // only accessing the length, otherwise it is used in accessing the value
2004 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2005
2006 if (!is_length_) {
2007 // Check index against actual arguments count. Use unsigned comparison to
2008 // get the negative check for free.
2009 // r0: actual number of parameter
2010 // r1: index
2011 // r2: adaptor frame point
2012 __ cmp(r1, r0);
2013 __ b(cs, &slow);
2014
2015 // Read the argument from the adaptor frame.
2016 __ sub(r3, r0, r1);
2017 __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
2018 __ ldr(r0, MemOperand(r3, kParamDisplacement));
2019 }
2020
2021 // Return to the calling function.
2022 __ mov(pc, lr);
2023
2024 if (!is_length_) {
1984 __ bind(&slow); 2025 __ bind(&slow);
1985 __ push(r0); 2026 __ push(r1);
1986 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); 2027 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1);
1987 } 2028 }
1988 } 2029 }
1989 2030
1990 2031
1991 #undef __ 2032 #undef __
1992 #define __ masm_-> 2033 #define __ masm_->
1993 2034
1994 2035
1995 void ArmCodeGenerator::GetReferenceProperty(Expression* key) { 2036 void ArmCodeGenerator::GetReferenceProperty(Expression* key) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
2078 case Token::SAR: { 2119 case Token::SAR: {
2079 __ pop(r0); // r0 : y 2120 __ pop(r0); // r0 : y
2080 __ pop(r1); // r1 : x 2121 __ pop(r1); // r1 : x
2081 GenericBinaryOpStub stub(op); 2122 GenericBinaryOpStub stub(op);
2082 __ CallStub(&stub); 2123 __ CallStub(&stub);
2083 break; 2124 break;
2084 } 2125 }
2085 2126
2086 case Token::DIV: { 2127 case Token::DIV: {
2087 __ mov(r0, Operand(1)); 2128 __ mov(r0, Operand(1));
2088 __ InvokeBuiltin("DIV", 1, CALL_JS); 2129 __ InvokeBuiltin(Builtins::DIV, CALL_JS);
2089 break; 2130 break;
2090 } 2131 }
2091 2132
2092 case Token::MOD: { 2133 case Token::MOD: {
2093 __ mov(r0, Operand(1)); 2134 __ mov(r0, Operand(1));
2094 __ InvokeBuiltin("MOD", 1, CALL_JS); 2135 __ InvokeBuiltin(Builtins::MOD, CALL_JS);
2095 break; 2136 break;
2096 } 2137 }
2097 2138
2098 case Token::COMMA: 2139 case Token::COMMA:
2099 __ pop(r0); 2140 __ pop(r0);
2100 // simply discard left value 2141 // simply discard left value
2101 __ pop(); 2142 __ pop();
2102 break; 2143 break;
2103 2144
2104 default: 2145 default:
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
2339 __ pop(r1); 2380 __ pop(r1);
2340 } 2381 }
2341 __ orr(r2, r0, Operand(r1)); 2382 __ orr(r2, r0, Operand(r1));
2342 __ tst(r2, Operand(kSmiTagMask)); 2383 __ tst(r2, Operand(kSmiTagMask));
2343 __ b(eq, &smi); 2384 __ b(eq, &smi);
2344 2385
2345 // Perform non-smi comparison by runtime call. 2386 // Perform non-smi comparison by runtime call.
2346 __ push(r1); 2387 __ push(r1);
2347 2388
2348 // Figure out which native to call and setup the arguments. 2389 // Figure out which native to call and setup the arguments.
2349 const char* native; 2390 Builtins::JavaScript native;
2350 int argc; 2391 int argc;
2351 if (cc == eq) { 2392 if (cc == eq) {
2352 native = strict ? "STRICT_EQUALS" : "EQUALS"; 2393 native = strict ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
2353 argc = 1; 2394 argc = 1;
2354 } else { 2395 } else {
2355 native = "COMPARE"; 2396 native = Builtins::COMPARE;
2356 int ncr; // NaN compare result 2397 int ncr; // NaN compare result
2357 if (cc == lt || cc == le) { 2398 if (cc == lt || cc == le) {
2358 ncr = GREATER; 2399 ncr = GREATER;
2359 } else { 2400 } else {
2360 ASSERT(cc == gt || cc == ge); // remaining cases 2401 ASSERT(cc == gt || cc == ge); // remaining cases
2361 ncr = LESS; 2402 ncr = LESS;
2362 } 2403 }
2363 __ push(r0); 2404 __ push(r0);
2364 __ mov(r0, Operand(Smi::FromInt(ncr))); 2405 __ mov(r0, Operand(Smi::FromInt(ncr)));
2365 argc = 2; 2406 argc = 2;
2366 } 2407 }
2367 2408
2368 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater) 2409 // Call the native; it returns -1 (less), 0 (equal), or 1 (greater)
2369 // tagged as a small integer. 2410 // tagged as a small integer.
2370 __ push(r0); 2411 __ push(r0);
2371 __ mov(r0, Operand(argc)); 2412 __ mov(r0, Operand(argc));
2372 __ InvokeBuiltin(native, argc, CALL_JS); 2413 __ InvokeBuiltin(native, CALL_JS);
2373 __ cmp(r0, Operand(0)); 2414 __ cmp(r0, Operand(0));
2374 __ b(&exit); 2415 __ b(&exit);
2375 2416
2376 // test smi equality by pointer comparison. 2417 // test smi equality by pointer comparison.
2377 __ bind(&smi); 2418 __ bind(&smi);
2378 __ cmp(r1, Operand(r0)); 2419 __ cmp(r1, Operand(r0));
2379 2420
2380 __ bind(&exit); 2421 __ bind(&exit);
2381 cc_reg_ = cc; 2422 cc_reg_ = cc;
2382 } 2423 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2419 masm->b(ne, &slow); 2460 masm->b(ne, &slow);
2420 2461
2421 // Fast-case: Invoke the function now. 2462 // Fast-case: Invoke the function now.
2422 // r1: pushed function 2463 // r1: pushed function
2423 ParameterCount actual(argc_); 2464 ParameterCount actual(argc_);
2424 masm->InvokeFunction(r1, actual, JUMP_FUNCTION); 2465 masm->InvokeFunction(r1, actual, JUMP_FUNCTION);
2425 2466
2426 // Slow-case: Non-function called. 2467 // Slow-case: Non-function called.
2427 masm->bind(&slow); 2468 masm->bind(&slow);
2428 masm->mov(r0, Operand(argc_)); // Setup the number of arguments. 2469 masm->mov(r0, Operand(argc_)); // Setup the number of arguments.
2429 masm->InvokeBuiltin("CALL_NON_FUNCTION", argc_, JUMP_JS); 2470 masm->InvokeBuiltin(Builtins::CALL_NON_FUNCTION, JUMP_JS);
2430 } 2471 }
2431 2472
2432 2473
2433 // Call the function on the stack with the given arguments. 2474 // Call the function on the stack with the given arguments.
2434 void ArmCodeGenerator::CallWithArguments(ZoneList<Expression*>* args, 2475 void ArmCodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
2435 int position) { 2476 int position) {
2436 // Push the arguments ("left-to-right") on the stack. 2477 // Push the arguments ("left-to-right") on the stack.
2437 for (int i = 0; i < args->length(); i++) { 2478 for (int i = 0; i < args->length(); i++) {
2438 Load(args->at(i)); 2479 Load(args->at(i));
2439 } 2480 }
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
2859 __ tst(r0, Operand(kSmiTagMask)); 2900 __ tst(r0, Operand(kSmiTagMask));
2860 __ b(eq, &primitive); 2901 __ b(eq, &primitive);
2861 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2902 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2862 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); 2903 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
2863 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); 2904 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
2864 __ b(hs, &jsobject); 2905 __ b(hs, &jsobject);
2865 2906
2866 __ bind(&primitive); 2907 __ bind(&primitive);
2867 __ push(r0); 2908 __ push(r0);
2868 __ mov(r0, Operand(0)); 2909 __ mov(r0, Operand(0));
2869 __ InvokeBuiltin("TO_OBJECT", 0, CALL_JS); 2910 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
2870 2911
2871 2912
2872 __ bind(&jsobject); 2913 __ bind(&jsobject);
2873 2914
2874 // Get the set of properties (as a FixedArray or Map). 2915 // Get the set of properties (as a FixedArray or Map).
2875 __ push(r0); // duplicate the object being enumerated 2916 __ push(r0); // duplicate the object being enumerated
2876 __ push(r0); 2917 __ push(r0);
2877 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 2918 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
2878 2919
2879 // If we got a Map, we can do a fast modification check. 2920 // If we got a Map, we can do a fast modification check.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2953 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 2994 __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
2954 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 2995 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
2955 __ cmp(r1, Operand(r2)); 2996 __ cmp(r1, Operand(r2));
2956 __ b(eq, &end_del_check); 2997 __ b(eq, &end_del_check);
2957 2998
2958 // Convert the entry to a string (or null if it isn't a property anymore). 2999 // Convert the entry to a string (or null if it isn't a property anymore).
2959 __ ldr(r0, MemOperand(sp, 4 * kPointerSize)); // push enumerable 3000 __ ldr(r0, MemOperand(sp, 4 * kPointerSize)); // push enumerable
2960 __ push(r0); 3001 __ push(r0);
2961 __ push(r3); // push entry 3002 __ push(r3); // push entry
2962 __ mov(r0, Operand(1)); 3003 __ mov(r0, Operand(1));
2963 __ InvokeBuiltin("FILTER_KEY", 1, CALL_JS); 3004 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_JS);
2964 __ mov(r3, Operand(r0)); 3005 __ mov(r3, Operand(r0));
2965 3006
2966 // If the property has been removed while iterating, we just skip it. 3007 // If the property has been removed while iterating, we just skip it.
2967 __ cmp(r3, Operand(Factory::null_value())); 3008 __ cmp(r3, Operand(Factory::null_value()));
2968 __ b(eq, &next); 3009 __ b(eq, &next);
2969 3010
2970 3011
2971 __ bind(&end_del_check); 3012 __ bind(&end_del_check);
2972 3013
2973 // Store the entry in the 'each' expression and take another spin in the loop. 3014 // Store the entry in the 'each' expression and take another spin in the loop.
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
3351 __ push(r0); 3392 __ push(r0);
3352 } 3393 }
3353 3394
3354 3395
3355 void ArmCodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 3396 void ArmCodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
3356 Comment cmnt(masm_, "[ RexExp Literal"); 3397 Comment cmnt(masm_, "[ RexExp Literal");
3357 3398
3358 // Retrieve the literal array and check the allocated entry. 3399 // Retrieve the literal array and check the allocated entry.
3359 3400
3360 // Load the function of this activation. 3401 // Load the function of this activation.
3361 __ ldr(r1, MemOperand(pp, 0)); 3402 __ ldr(r1, FunctionOperand());
3362 3403
3363 // Load the literals array of the function. 3404 // Load the literals array of the function.
3364 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 3405 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
3365 3406
3366 // Load the literal at the ast saved index. 3407 // Load the literal at the ast saved index.
3367 int literal_offset = 3408 int literal_offset =
3368 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 3409 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
3369 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 3410 __ ldr(r2, FieldMemOperand(r1, literal_offset));
3370 3411
3371 Label done; 3412 Label done;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3424 3465
3425 3466
3426 void ArmCodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 3467 void ArmCodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
3427 Comment cmnt(masm_, "[ ObjectLiteral"); 3468 Comment cmnt(masm_, "[ ObjectLiteral");
3428 3469
3429 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 3470 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
3430 3471
3431 // Retrieve the literal array and check the allocated entry. 3472 // Retrieve the literal array and check the allocated entry.
3432 3473
3433 // Load the function of this activation. 3474 // Load the function of this activation.
3434 __ ldr(r1, MemOperand(pp, 0)); 3475 __ ldr(r1, FunctionOperand());
3435 3476
3436 // Load the literals array of the function. 3477 // Load the literals array of the function.
3437 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset)); 3478 __ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
3438 3479
3439 // Load the literal at the ast saved index. 3480 // Load the literal at the ast saved index.
3440 int literal_offset = 3481 int literal_offset =
3441 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 3482 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
3442 __ ldr(r2, FieldMemOperand(r1, literal_offset)); 3483 __ ldr(r2, FieldMemOperand(r1, literal_offset));
3443 3484
3444 // Check whether we need to materialize the object literal boilerplate. 3485 // Check whether we need to materialize the object literal boilerplate.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3495 } 3536 }
3496 } 3537 }
3497 3538
3498 3539
3499 void ArmCodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { 3540 void ArmCodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
3500 Comment cmnt(masm_, "[ ArrayLiteral"); 3541 Comment cmnt(masm_, "[ ArrayLiteral");
3501 3542
3502 // Call runtime to create the array literal. 3543 // Call runtime to create the array literal.
3503 __ mov(r0, Operand(node->literals())); 3544 __ mov(r0, Operand(node->literals()));
3504 __ push(r0); 3545 __ push(r0);
3505 // TODO(1332579): The second argument to CreateArrayLiteral is 3546 // Load the function of this frame.
3506 // supposed to be the literals array of the function of this frame. 3547 __ ldr(r0, FunctionOperand());
3507 // Until the new ARM calling convention is in place, that function 3548 __ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
3508 // is not always available. Therefore, on ARM we pass in the hole
3509 // until the new calling convention is in place.
3510 __ mov(r0, Operand(Factory::the_hole_value()));
3511 __ push(r0); 3549 __ push(r0);
3512 __ CallRuntime(Runtime::kCreateArrayLiteral, 2); 3550 __ CallRuntime(Runtime::kCreateArrayLiteral, 2);
3513 3551
3514 // Push the resulting array literal on the stack. 3552 // Push the resulting array literal on the stack.
3515 __ push(r0); 3553 __ push(r0);
3516 3554
3517 // Generate code to set the elements in the array that are not 3555 // Generate code to set the elements in the array that are not
3518 // literals. 3556 // literals.
3519 for (int i = 0; i < node->values()->length(); i++) { 3557 for (int i = 0; i < node->values()->length(); i++) {
3520 Expression* value = node->values()->at(i); 3558 Expression* value = node->values()->at(i);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
3753 Load(node->expression()); 3791 Load(node->expression());
3754 LoadGlobal(); 3792 LoadGlobal();
3755 3793
3756 // Push the arguments ("left-to-right") on the stack. 3794 // Push the arguments ("left-to-right") on the stack.
3757 ZoneList<Expression*>* args = node->arguments(); 3795 ZoneList<Expression*>* args = node->arguments();
3758 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 3796 for (int i = 0; i < args->length(); i++) Load(args->at(i));
3759 3797
3760 // r0: the number of arguments. 3798 // r0: the number of arguments.
3761 __ mov(r0, Operand(args->length())); 3799 __ mov(r0, Operand(args->length()));
3762 3800
3801 // Load the function into r1 as per calling convention.
3802 __ ldr(r1, MemOperand(sp, (args->length() + 1) * kPointerSize));
3803
3763 // Call the construct call builtin that handles allocation and 3804 // Call the construct call builtin that handles allocation and
3764 // constructor invocation. 3805 // constructor invocation.
3765 __ RecordPosition(position); 3806 __ RecordPosition(position);
3766 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 3807 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
3767 js_construct_call); 3808 js_construct_call);
3768 3809
3769 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)). 3810 // Discard old TOS value and push r0 on the stack (same as Pop(), push(r0)).
3770 __ str(r0, MemOperand(sp, 0 * kPointerSize)); 3811 __ str(r0, MemOperand(sp, 0 * kPointerSize));
3771 } 3812 }
3772 3813
3773 3814
3774 void ArmCodeGenerator::GenerateSetThisFunction(ZoneList<Expression*>* args) { 3815 void ArmCodeGenerator::GenerateSetThisFunction(ZoneList<Expression*>* args) {
3775 ASSERT(args->length() == 1); 3816 __ stop("ArmCodeGenerator::GenerateSetThisFunction - unreachable");
3776 Load(args->at(0));
3777 __ ldr(r0, MemOperand(sp, 0));
3778 __ str(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
3779 } 3817 }
3780 3818
3781 3819
3782 void ArmCodeGenerator::GenerateGetThisFunction(ZoneList<Expression*>* args) { 3820 void ArmCodeGenerator::GenerateGetThisFunction(ZoneList<Expression*>* args) {
3783 ASSERT(args->length() == 0); 3821 __ stop("ArmCodeGenerator::GenerateGetThisFunction - unreachable");
3784 __ ldr(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
3785 __ push(r0);
3786 } 3822 }
3787 3823
3788 3824
3789 void ArmCodeGenerator::GenerateSetThis(ZoneList<Expression*>* args) { 3825 void ArmCodeGenerator::GenerateSetThis(ZoneList<Expression*>* args) {
3790 ASSERT(args->length() == 1); 3826 __ stop("ArmCodeGenerator::GenerateSetThis - unreachable");
3791 Load(args->at(0));
3792 __ ldr(r0, MemOperand(sp, 0));
3793 __ str(r0, MemOperand(pp, JavaScriptFrameConstants::kReceiverOffset));
3794 } 3827 }
3795 3828
3796 3829
3797 void ArmCodeGenerator::GenerateSetArgumentsLength(ZoneList<Expression*>* args) { 3830 void ArmCodeGenerator::GenerateSetArgumentsLength(ZoneList<Expression*>* args) {
3798 ASSERT(args->length() == 1); 3831 __ stop("ArmCodeGenerator::GenerateSetArgumentsLength - unreachable");
3799 Load(args->at(0));
3800 __ pop(r0);
3801 __ mov(r0, Operand(r0, LSR, kSmiTagSize));
3802 __ str(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset));
3803 __ mov(r0, Operand(Smi::FromInt(0))); // return a meaningful value
3804 __ push(r0);
3805 } 3832 }
3806 3833
3807 3834
3808 void ArmCodeGenerator::GenerateGetArgumentsLength(ZoneList<Expression*>* args) { 3835 void ArmCodeGenerator::GenerateGetArgumentsLength(ZoneList<Expression*>* args) {
3809 ASSERT(args->length() == 1); 3836 __ stop("ArmCodeGenerator::GenerateGetArgumentsLength - unreachable");
3810 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset));
3811 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
3812 __ push(r0);
3813 } 3837 }
3814 3838
3815 3839
3816 void ArmCodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3840 void ArmCodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3817 ASSERT(args->length() == 1); 3841 ASSERT(args->length() == 1);
3818 Label leave; 3842 Label leave;
3819 Load(args->at(0)); 3843 Load(args->at(0));
3820 __ pop(r0); // r0 contains object. 3844 __ pop(r0); // r0 contains object.
3821 // if (object->IsSmi()) return the object. 3845 // if (object->IsSmi()) return the object.
3822 __ tst(r0, Operand(kSmiTagMask)); 3846 __ tst(r0, Operand(kSmiTagMask));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3856 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); 3880 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
3857 __ RecordWrite(r1, r2, r3); 3881 __ RecordWrite(r1, r2, r3);
3858 // Leave. 3882 // Leave.
3859 __ bind(&leave); 3883 __ bind(&leave);
3860 __ push(r0); 3884 __ push(r0);
3861 } 3885 }
3862 3886
3863 3887
3864 void ArmCodeGenerator::GenerateTailCallWithArguments( 3888 void ArmCodeGenerator::GenerateTailCallWithArguments(
3865 ZoneList<Expression*>* args) { 3889 ZoneList<Expression*>* args) {
3866 // r0 = number of arguments (smi) 3890 __ stop("ArmCodeGenerator::GenerateTailCallWithArguments - unreachable");
3867 ASSERT(args->length() == 1);
3868 Load(args->at(0));
3869 __ pop(r0);
3870 __ mov(r0, Operand(r0, LSR, kSmiTagSize));
3871
3872 // r1 = new function (previously written to stack)
3873 __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
3874
3875 // Reset parameter pointer and frame pointer to previous frame
3876 ExitJSFrame(DO_NOT_RETURN);
3877
3878 // Jump (tail-call) to the function in register r1.
3879 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
3880 __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
3881 __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
3882 __ add(pc, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
3883 } 3891 }
3884 3892
3885 3893
3886 void ArmCodeGenerator::GenerateSetArgument(ZoneList<Expression*>* args) { 3894 void ArmCodeGenerator::GenerateSetArgument(ZoneList<Expression*>* args) {
3887 ASSERT(args->length() == 3); 3895 __ stop("ArmCodeGenerator::GenerateSetArgument - unreachable");
3888 // r0 = args[i]; r1 = i
3889 Comment cmnt(masm_, "[ GenerateSetArgument");
3890 Load(args->at(1)); // args[i] (value)
3891 Load(args->at(0)); // i
3892 __ pop(r1); // i
3893 __ pop(r0); // value
3894 #if defined(DEBUG)
3895 { Label L;
3896 __ tst(r1, Operand(kSmiTagMask));
3897 __ b(eq, &L);
3898 __ stop("SMI expected");
3899 __ bind(&L);
3900 }
3901 #endif // defined(DEBUG)
3902 __ add(r2, pp, Operand(JavaScriptFrameConstants::kParam0Offset));
3903 __ str(r0,
3904 MemOperand(r2, r1, LSL, kPointerSizeLog2 - kSmiTagSize, NegOffset));
3905 __ push(r0);
3906 } 3896 }
3907 3897
3908 3898
3909 void ArmCodeGenerator::GenerateSquashFrame(ZoneList<Expression*>* args) { 3899 void ArmCodeGenerator::GenerateSquashFrame(ZoneList<Expression*>* args) {
3910 ASSERT(args->length() == 2); 3900 __ stop("ArmCodeGenerator::GenerateSquashFrame - unreachable");
3911 Load(args->at(0)); // old number of arguments
3912 Load(args->at(1)); // new number of arguments, r1 > r0
3913 __ pop(r0);
3914 __ mov(r0, Operand(r0, LSR, kSmiTagSize));
3915 __ pop(r1);
3916 __ mov(r1, Operand(r1, LSR, kSmiTagSize));
3917 // r1 = number of words to move stack.
3918 __ sub(r1, r1, Operand(r0));
3919 // r2 is source.
3920 __ add(r2, fp, Operand(StandardFrameConstants::kCallerPCOffset));
3921 // Move down frame pointer fp.
3922 __ add(fp, fp, Operand(r1, LSL, kPointerSizeLog2));
3923 // r1 is destination.
3924 __ add(r1, fp, Operand(StandardFrameConstants::kCallerPCOffset));
3925
3926 Label move;
3927 __ bind(&move);
3928 __ ldr(r3, MemOperand(r2, -kPointerSize, PostIndex));
3929 __ str(r3, MemOperand(r1, -kPointerSize, PostIndex));
3930 __ cmp(r2, Operand(sp));
3931 __ b(ne, &move);
3932 __ ldr(r3, MemOperand(r2));
3933 __ str(r3, MemOperand(r1));
3934
3935 // Move down stack pointer esp.
3936 __ mov(sp, Operand(r1));
3937 // Put something GC-able in r0.
3938 __ mov(r0, Operand(Smi::FromInt(0)));
3939 __ push(r0);
3940 } 3901 }
3941 3902
3942 3903
3943 void ArmCodeGenerator::GenerateExpandFrame(ZoneList<Expression*>* args) { 3904 void ArmCodeGenerator::GenerateExpandFrame(ZoneList<Expression*>* args) {
3944 ASSERT(args->length() == 2); 3905 __ stop("ArmCodeGenerator::GenerateExpandFrame - unreachable");
3945 Load(args->at(1));
3946 Load(args->at(0));
3947 __ pop(r0); // new number of arguments
3948 __ pop(r1); // old number of arguments, r1 > r0
3949 __ mov(r1, Operand(r1, LSR, kSmiTagSize));
3950
3951 // r1 = number of words to move stack.
3952 __ sub(r1, r1, Operand(r0, LSR, kSmiTagSize));
3953 Label end_of_expand_frame;
3954 if (FLAG_check_stack) {
3955 Label not_too_big;
3956 __ sub(r2, sp, Operand(r1, LSL, kPointerSizeLog2));
3957 __ mov(ip, Operand(ExternalReference::address_of_stack_guard_limit()));
3958 __ ldr(ip, MemOperand(ip));
3959 __ cmp(r2, Operand(ip));
3960 __ b(gt, &not_too_big);
3961 __ mov(r0, Operand(Factory::false_value()));
3962 __ b(&end_of_expand_frame);
3963 __ bind(&not_too_big);
3964 }
3965 // r3 is source.
3966 __ mov(r3, Operand(sp));
3967 // r0 is copy limit + 1 word
3968 __ add(r0, fp,
3969 Operand(StandardFrameConstants::kCallerPCOffset + kPointerSize));
3970 // Move up frame pointer fp.
3971 __ sub(fp, fp, Operand(r1, LSL, kPointerSizeLog2));
3972 // Move up stack pointer sp.
3973 __ sub(sp, sp, Operand(r1, LSL, kPointerSizeLog2));
3974 // r1 is destination (r1 = source - r1).
3975 __ mov(r2, Operand(0));
3976 __ sub(r2, r2, Operand(r1, LSL, kPointerSizeLog2));
3977 __ add(r1, r3, Operand(r2));
3978
3979 Label move;
3980 __ bind(&move);
3981 __ ldr(r2, MemOperand(r3, kPointerSize, PostIndex));
3982 __ str(r2, MemOperand(r1, kPointerSize, PostIndex));
3983 __ cmp(r3, Operand(r0));
3984 __ b(ne, &move);
3985
3986 // Put success value in top of stack
3987 __ mov(r0, Operand(Factory::true_value()));
3988 __ bind(&end_of_expand_frame);
3989 __ push(r0);
3990 } 3906 }
3991 3907
3992 3908
3993 void ArmCodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { 3909 void ArmCodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
3994 ASSERT(args->length() == 1); 3910 ASSERT(args->length() == 1);
3995 Load(args->at(0)); 3911 Load(args->at(0));
3996 __ pop(r0); 3912 __ pop(r0);
3997 __ tst(r0, Operand(kSmiTagMask)); 3913 __ tst(r0, Operand(kSmiTagMask));
3998 cc_reg_ = eq; 3914 cc_reg_ = eq;
3999 } 3915 }
4000 3916
4001 3917
4002 void ArmCodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3918 void ArmCodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
4003 ASSERT(args->length() == 1); 3919 ASSERT(args->length() == 1);
4004 Load(args->at(0)); 3920 Load(args->at(0));
4005 __ pop(r0); 3921 __ pop(r0);
4006 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); 3922 __ tst(r0, Operand(kSmiTagMask | 0x80000000));
4007 cc_reg_ = eq; 3923 cc_reg_ = eq;
4008 } 3924 }
4009 3925
4010 3926
4011
4012 // This should generate code that performs a charCodeAt() call or returns 3927 // This should generate code that performs a charCodeAt() call or returns
4013 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3928 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
4014 // It is not yet implemented on ARM, so it always goes to the slow case. 3929 // It is not yet implemented on ARM, so it always goes to the slow case.
4015 void ArmCodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3930 void ArmCodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
4016 ASSERT(args->length() == 2); 3931 ASSERT(args->length() == 2);
4017 __ mov(r0, Operand(Factory::undefined_value())); 3932 __ mov(r0, Operand(Factory::undefined_value()));
4018 __ push(r0); 3933 __ push(r0);
4019 } 3934 }
4020 3935
4021 3936
4022
4023 // This is used in the implementation of apply on ia32 but it is not
4024 // used on ARM yet.
4025 void ArmCodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3937 void ArmCodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
4026 __ stop("ArmCodeGenerator::GenerateIsArray"); 3938 ASSERT(args->length() == 1);
3939 Load(args->at(0));
3940 Label answer;
3941 // We need the CC bits to come out as not_equal in the case where the
3942 // object is a smi. This can't be done with the usual test opcode so
3943 // we use XOR to get the right CC bits.
3944 __ pop(r0);
3945 __ and_(r1, r0, Operand(kSmiTagMask));
3946 __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
3947 __ b(ne, &answer);
3948 // It is a heap object - get the map.
3949 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
3950 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3951 // Check if the object is a JS array or not.
3952 __ cmp(r1, Operand(JS_ARRAY_TYPE));
3953 __ bind(&answer);
4027 cc_reg_ = eq; 3954 cc_reg_ = eq;
4028 } 3955 }
4029 3956
4030 3957
4031 void ArmCodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 3958 void ArmCodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
4032 ASSERT(args->length() == 0); 3959 ASSERT(args->length() == 0);
4033 3960
4034 // Seed the result with the formal parameters count, which will be used 3961 // Seed the result with the formal parameters count, which will be used
4035 // in case no arguments adaptor frame is found below the current frame. 3962 // in case no arguments adaptor frame is found below the current frame.
4036 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters()))); 3963 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
4037 3964
4038 // Call the shared stub to get to the arguments.length. 3965 // Call the shared stub to get to the arguments.length.
4039 ArgumentsAccessStub stub(true); 3966 ArgumentsAccessStub stub(true);
4040 __ CallStub(&stub); 3967 __ CallStub(&stub);
4041 __ push(r0); 3968 __ push(r0);
4042 } 3969 }
4043 3970
4044 3971
4045 void ArmCodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { 3972 void ArmCodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
4046 ASSERT(args->length() == 1); 3973 ASSERT(args->length() == 1);
4047 3974
4048 // Load the key onto the stack and set register r1 to the formal 3975 // Satisfy contract with ArgumentsAccessStub:
4049 // parameters count for the currently executing function. 3976 // Load the key into r1 and the formal parameters count into r0.
4050 Load(args->at(0)); 3977 Load(args->at(0));
4051 __ pop(r0); 3978 __ pop(r1);
4052 __ mov(r1, Operand(Smi::FromInt(scope_->num_parameters()))); 3979 __ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
4053 3980
4054 // Call the shared stub to get to arguments[key]. 3981 // Call the shared stub to get to arguments[key].
4055 ArgumentsAccessStub stub(false); 3982 ArgumentsAccessStub stub(false);
4056 __ CallStub(&stub); 3983 __ CallStub(&stub);
4057 __ push(r0); 3984 __ push(r0);
4058 } 3985 }
4059 3986
4060 3987
4061 void ArmCodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 3988 void ArmCodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
4062 ASSERT(args->length() == 2); 3989 ASSERT(args->length() == 2);
4063 3990
4064 // Load the two objects into registers and perform the comparison. 3991 // Load the two objects into registers and perform the comparison.
4065 Load(args->at(0)); 3992 Load(args->at(0));
4066 Load(args->at(1)); 3993 Load(args->at(1));
4067 __ pop(r0); 3994 __ pop(r0);
4068 __ pop(r1); 3995 __ pop(r1);
4069 __ cmp(r0, Operand(r1)); 3996 __ cmp(r0, Operand(r1));
4070 cc_reg_ = eq; 3997 cc_reg_ = eq;
4071 } 3998 }
4072 3999
4073 4000
4074 void ArmCodeGenerator::GenerateShiftDownAndTailCall( 4001 void ArmCodeGenerator::GenerateShiftDownAndTailCall(
4075 ZoneList<Expression*>* args) { 4002 ZoneList<Expression*>* args) {
4076 // r0 = number of arguments 4003 __ stop("ArmCodeGenerator::GenerateShiftDownAndTailCall - unreachable");
4077 ASSERT(args->length() == 1);
4078 Load(args->at(0));
4079 __ pop(r0);
4080 __ mov(r0, Operand(r0, LSR, kSmiTagSize));
4081
4082 // Get the 'this' function and exit the frame without returning.
4083 __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
4084 ExitJSFrame(DO_NOT_RETURN);
4085 // return address in lr
4086
4087 // Move arguments one element down the stack.
4088 Label move;
4089 Label moved;
4090 __ sub(r2, r0, Operand(0), SetCC);
4091 __ b(eq, &moved);
4092 __ bind(&move);
4093 __ sub(ip, r2, Operand(1));
4094 __ ldr(r3, MemOperand(sp, ip, LSL, kPointerSizeLog2));
4095 __ str(r3, MemOperand(sp, r2, LSL, kPointerSizeLog2));
4096 __ sub(r2, r2, Operand(1), SetCC);
4097 __ b(ne, &move);
4098 __ bind(&moved);
4099
4100 // Remove the TOS (copy of last argument)
4101 __ pop();
4102
4103 // Jump (tail-call) to the function in register r1.
4104 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
4105 __ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
4106 __ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
4107 __ add(pc, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
4108
4109 return;
4110 } 4004 }
4111 4005
4112 4006
4113 void ArmCodeGenerator::VisitCallRuntime(CallRuntime* node) { 4007 void ArmCodeGenerator::VisitCallRuntime(CallRuntime* node) {
4114 if (CheckForInlineRuntimeCall(node)) 4008 if (CheckForInlineRuntimeCall(node)) return;
4115 return;
4116 4009
4117 ZoneList<Expression*>* args = node->arguments(); 4010 ZoneList<Expression*>* args = node->arguments();
4118 Comment cmnt(masm_, "[ CallRuntime"); 4011 Comment cmnt(masm_, "[ CallRuntime");
4119 Runtime::Function* function = node->function(); 4012 Runtime::Function* function = node->function();
4120 4013
4121 if (function != NULL) { 4014 if (function != NULL) {
4122 // Push the arguments ("left-to-right"). 4015 // Push the arguments ("left-to-right").
4123 for (int i = 0; i < args->length(); i++) Load(args->at(i)); 4016 for (int i = 0; i < args->length(); i++) Load(args->at(i));
4124 4017
4125 // Call the C runtime function. 4018 // Call the C runtime function.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4160 true); 4053 true);
4161 cc_reg_ = NegateCondition(cc_reg_); 4054 cc_reg_ = NegateCondition(cc_reg_);
4162 4055
4163 } else if (op == Token::DELETE) { 4056 } else if (op == Token::DELETE) {
4164 Property* property = node->expression()->AsProperty(); 4057 Property* property = node->expression()->AsProperty();
4165 Variable* variable = node->expression()->AsVariableProxy()->AsVariable(); 4058 Variable* variable = node->expression()->AsVariableProxy()->AsVariable();
4166 if (property != NULL) { 4059 if (property != NULL) {
4167 Load(property->obj()); 4060 Load(property->obj());
4168 Load(property->key()); 4061 Load(property->key());
4169 __ mov(r0, Operand(1)); // not counting receiver 4062 __ mov(r0, Operand(1)); // not counting receiver
4170 __ InvokeBuiltin("DELETE", 1, CALL_JS); 4063 __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
4171 4064
4172 } else if (variable != NULL) { 4065 } else if (variable != NULL) {
4173 Slot* slot = variable->slot(); 4066 Slot* slot = variable->slot();
4174 if (variable->is_global()) { 4067 if (variable->is_global()) {
4175 LoadGlobal(); 4068 LoadGlobal();
4176 __ mov(r0, Operand(variable->name())); 4069 __ mov(r0, Operand(variable->name()));
4177 __ push(r0); 4070 __ push(r0);
4178 __ mov(r0, Operand(1)); // not counting receiver 4071 __ mov(r0, Operand(1)); // not counting receiver
4179 __ InvokeBuiltin("DELETE", 1, CALL_JS); 4072 __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
4180 4073
4181 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { 4074 } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
4182 // lookup the context holding the named variable 4075 // lookup the context holding the named variable
4183 __ push(cp); 4076 __ push(cp);
4184 __ mov(r0, Operand(variable->name())); 4077 __ mov(r0, Operand(variable->name()));
4185 __ push(r0); 4078 __ push(r0);
4186 __ CallRuntime(Runtime::kLookupContext, 2); 4079 __ CallRuntime(Runtime::kLookupContext, 2);
4187 // r0: context 4080 // r0: context
4188 __ push(r0); 4081 __ push(r0);
4189 __ mov(r0, Operand(variable->name())); 4082 __ mov(r0, Operand(variable->name()));
4190 __ push(r0); 4083 __ push(r0);
4191 __ mov(r0, Operand(1)); // not counting receiver 4084 __ mov(r0, Operand(1)); // not counting receiver
4192 __ InvokeBuiltin("DELETE", 1, CALL_JS); 4085 __ InvokeBuiltin(Builtins::DELETE, CALL_JS);
4193 4086
4194 } else { 4087 } else {
4195 // Default: Result of deleting non-global, not dynamically 4088 // Default: Result of deleting non-global, not dynamically
4196 // introduced variables is false. 4089 // introduced variables is false.
4197 __ mov(r0, Operand(Factory::false_value())); 4090 __ mov(r0, Operand(Factory::false_value()));
4198 } 4091 }
4199 4092
4200 } else { 4093 } else {
4201 // Default: Result of deleting expressions is true. 4094 // Default: Result of deleting expressions is true.
4202 Load(node->expression()); // may have side-effects 4095 Load(node->expression()); // may have side-effects
(...skipping 27 matching lines...) Expand all
4230 4123
4231 case Token::BIT_NOT: { 4124 case Token::BIT_NOT: {
4232 // smi check 4125 // smi check
4233 Label smi_label; 4126 Label smi_label;
4234 Label continue_label; 4127 Label continue_label;
4235 __ tst(r0, Operand(kSmiTagMask)); 4128 __ tst(r0, Operand(kSmiTagMask));
4236 __ b(eq, &smi_label); 4129 __ b(eq, &smi_label);
4237 4130
4238 __ push(r0); 4131 __ push(r0);
4239 __ mov(r0, Operand(0)); // not counting receiver 4132 __ mov(r0, Operand(0)); // not counting receiver
4240 __ InvokeBuiltin("BIT_NOT", 0, CALL_JS); 4133 __ InvokeBuiltin(Builtins::BIT_NOT, CALL_JS);
4241 4134
4242 __ b(&continue_label); 4135 __ b(&continue_label);
4243 __ bind(&smi_label); 4136 __ bind(&smi_label);
4244 __ mvn(r0, Operand(r0)); 4137 __ mvn(r0, Operand(r0));
4245 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag 4138 __ bic(r0, r0, Operand(kSmiTagMask)); // bit-clear inverted smi-tag
4246 __ bind(&continue_label); 4139 __ bind(&continue_label);
4247 break; 4140 break;
4248 } 4141 }
4249 4142
4250 case Token::VOID: 4143 case Token::VOID:
4251 // since the stack top is cached in r0, popping and then 4144 // since the stack top is cached in r0, popping and then
4252 // pushing a value can be done by just writing to r0. 4145 // pushing a value can be done by just writing to r0.
4253 __ mov(r0, Operand(Factory::undefined_value())); 4146 __ mov(r0, Operand(Factory::undefined_value()));
4254 break; 4147 break;
4255 4148
4256 case Token::ADD: { 4149 case Token::ADD: {
4257 // Smi check. 4150 // Smi check.
4258 Label continue_label; 4151 Label continue_label;
4259 __ tst(r0, Operand(kSmiTagMask)); 4152 __ tst(r0, Operand(kSmiTagMask));
4260 __ b(eq, &continue_label); 4153 __ b(eq, &continue_label);
4261 __ push(r0); 4154 __ push(r0);
4262 __ mov(r0, Operand(0)); // not counting receiver 4155 __ mov(r0, Operand(0)); // not counting receiver
4263 __ InvokeBuiltin("TO_NUMBER", 0, CALL_JS); 4156 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
4264 __ bind(&continue_label); 4157 __ bind(&continue_label);
4265 break; 4158 break;
4266 } 4159 }
4267 default: 4160 default:
4268 UNREACHABLE(); 4161 UNREACHABLE();
4269 } 4162 }
4270 __ push(r0); // r0 has result 4163 __ push(r0); // r0 has result
4271 } 4164 }
4272 } 4165 }
4273 4166
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
4651 case Token::GTE: 4544 case Token::GTE:
4652 Comparison(ge); 4545 Comparison(ge);
4653 break; 4546 break;
4654 4547
4655 case Token::EQ_STRICT: 4548 case Token::EQ_STRICT:
4656 Comparison(eq, true); 4549 Comparison(eq, true);
4657 break; 4550 break;
4658 4551
4659 case Token::IN: 4552 case Token::IN:
4660 __ mov(r0, Operand(1)); // not counting receiver 4553 __ mov(r0, Operand(1)); // not counting receiver
4661 __ InvokeBuiltin("IN", 1, CALL_JS); 4554 __ InvokeBuiltin(Builtins::IN, CALL_JS);
4662 __ push(r0); 4555 __ push(r0);
4663 break; 4556 break;
4664 4557
4665 case Token::INSTANCEOF: 4558 case Token::INSTANCEOF:
4666 __ mov(r0, Operand(1)); // not counting receiver 4559 __ mov(r0, Operand(1)); // not counting receiver
4667 __ InvokeBuiltin("INSTANCE_OF", 1, CALL_JS); 4560 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_JS);
4668 __ push(r0); 4561 __ push(r0);
4669 break; 4562 break;
4670 4563
4671 default: 4564 default:
4672 UNREACHABLE(); 4565 UNREACHABLE();
4673 } 4566 }
4674 } 4567 }
4675 4568
4676 4569
4677 void ArmCodeGenerator::RecordStatementPosition(Node* node) { 4570 void ArmCodeGenerator::RecordStatementPosition(Node* node) {
4678 if (FLAG_debug_info) { 4571 if (FLAG_debug_info) {
4679 int statement_pos = node->statement_pos(); 4572 int statement_pos = node->statement_pos();
4680 if (statement_pos == kNoPosition) return; 4573 if (statement_pos == kNoPosition) return;
4681 __ RecordStatementPosition(statement_pos); 4574 __ RecordStatementPosition(statement_pos);
4682 } 4575 }
4683 } 4576 }
4684 4577
4685 4578
4686 void ArmCodeGenerator::EnterJSFrame(int argc) { 4579 void ArmCodeGenerator::EnterJSFrame() {
4687 __ EnterJSFrame(argc); 4580 #if defined(DEBUG)
4581 { Label done, fail;
4582 __ tst(r1, Operand(kSmiTagMask));
4583 __ b(eq, &fail);
4584 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
4585 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
4586 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
4587 __ b(eq, &done);
4588 __ bind(&fail);
4589 __ stop("ArmCodeGenerator::EnterJSFrame - r1 not a function");
4590 __ bind(&done);
4591 }
4592 #endif // DEBUG
4593
4594 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
4595 __ add(fp, sp, Operand(2 * kPointerSize)); // Adjust FP to point to saved FP.
4688 } 4596 }
4689 4597
4690 4598
4691 void ArmCodeGenerator::ExitJSFrame(ExitJSFlag flag) { 4599 void ArmCodeGenerator::ExitJSFrame() {
4692 JSExitStub stub(flag); 4600 // Drop the execution stack down to the frame pointer and restore the caller
4693 __ CallJSExitStub(&stub); 4601 // frame pointer and return address.
4602 __ mov(sp, fp);
4603 __ ldm(ia_w, sp, fp.bit() | lr.bit());
4694 } 4604 }
4695 4605
4696 4606
4697 #undef __ 4607 #undef __
4698 4608
4699 4609
4700 // ----------------------------------------------------------------------------- 4610 // -----------------------------------------------------------------------------
4701 // CodeGenerator interface 4611 // CodeGenerator interface
4702 4612
4703 // MakeCode() is just a wrapper for CodeGenerator::MakeCode() 4613 // MakeCode() is just a wrapper for CodeGenerator::MakeCode()
4704 // so we don't have to expose the entire CodeGenerator class in 4614 // so we don't have to expose the entire CodeGenerator class in
4705 // the .h file. 4615 // the .h file.
4706 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun, 4616 Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
4707 Handle<Script> script, 4617 Handle<Script> script,
4708 bool is_eval) { 4618 bool is_eval) {
4709 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval); 4619 Handle<Code> code = ArmCodeGenerator::MakeCode(fun, script, is_eval);
4710 if (!code.is_null()) { 4620 if (!code.is_null()) {
4711 Counters::total_compiled_code_size.Increment(code->instruction_size()); 4621 Counters::total_compiled_code_size.Increment(code->instruction_size());
4712 } 4622 }
4713 return code; 4623 return code;
4714 } 4624 }
4715 4625
4716 4626
4717 } } // namespace v8::internal 4627 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/builtins-ia32.cc ('k') | src/disasm-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698