OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
8 | 8 |
9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 #ifdef DEBUG | 116 #ifdef DEBUG |
117 if (strlen(FLAG_stop_at) > 0 && | 117 if (strlen(FLAG_stop_at) > 0 && |
118 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 118 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
119 __ stop("stop-at"); | 119 __ stop("stop-at"); |
120 } | 120 } |
121 #endif | 121 #endif |
122 | 122 |
123 // Sloppy mode functions and builtins need to replace the receiver with the | 123 // Sloppy mode functions and builtins need to replace the receiver with the |
124 // global proxy when called as functions (without an explicit receiver | 124 // global proxy when called as functions (without an explicit receiver |
125 // object). | 125 // object). |
126 if (info->strict_mode() == SLOPPY && !info->is_native()) { | 126 if (is_sloppy(info->language_mode()) && !info->is_native()) { |
127 Label ok; | 127 Label ok; |
128 int receiver_offset = info->scope()->num_parameters() * kPointerSize; | 128 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
129 __ LoadP(r5, MemOperand(sp, receiver_offset), r0); | 129 __ LoadP(r5, MemOperand(sp, receiver_offset), r0); |
130 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); | 130 __ CompareRoot(r5, Heap::kUndefinedValueRootIndex); |
131 __ bne(&ok); | 131 __ bne(&ok); |
132 | 132 |
133 __ LoadP(r5, GlobalObjectOperand()); | 133 __ LoadP(r5, GlobalObjectOperand()); |
134 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); | 134 __ LoadP(r5, FieldMemOperand(r5, GlobalObject::kGlobalProxyOffset)); |
135 | 135 |
136 __ StoreP(r5, MemOperand(sp, receiver_offset), r0); | 136 __ StoreP(r5, MemOperand(sp, receiver_offset), r0); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 int offset = num_parameters * kPointerSize; | 260 int offset = num_parameters * kPointerSize; |
261 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 261 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
262 __ LoadSmiLiteral(r4, Smi::FromInt(num_parameters)); | 262 __ LoadSmiLiteral(r4, Smi::FromInt(num_parameters)); |
263 __ Push(r6, r5, r4); | 263 __ Push(r6, r5, r4); |
264 | 264 |
265 // Arguments to ArgumentsAccessStub: | 265 // Arguments to ArgumentsAccessStub: |
266 // function, receiver address, parameter count. | 266 // function, receiver address, parameter count. |
267 // The stub will rewrite receiever and parameter count if the previous | 267 // The stub will rewrite receiever and parameter count if the previous |
268 // stack frame was an arguments adapter frame. | 268 // stack frame was an arguments adapter frame. |
269 ArgumentsAccessStub::Type type; | 269 ArgumentsAccessStub::Type type; |
270 if (strict_mode() == STRICT) { | 270 if (is_strict(language_mode())) { |
271 type = ArgumentsAccessStub::NEW_STRICT; | 271 type = ArgumentsAccessStub::NEW_STRICT; |
272 } else if (function()->has_duplicate_parameters()) { | 272 } else if (function()->has_duplicate_parameters()) { |
273 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; | 273 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
274 } else { | 274 } else { |
275 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; | 275 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
276 } | 276 } |
277 ArgumentsAccessStub stub(isolate(), type); | 277 ArgumentsAccessStub stub(isolate(), type); |
278 __ CallStub(&stub); | 278 __ CallStub(&stub); |
279 | 279 |
280 SetVar(arguments, r3, r4, r5); | 280 SetVar(arguments, r3, r4, r5); |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 Comment cmnt(masm_, "[ ForInStatement"); | 1059 Comment cmnt(masm_, "[ ForInStatement"); |
1060 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); | 1060 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot(); |
1061 SetStatementPosition(stmt); | 1061 SetStatementPosition(stmt); |
1062 | 1062 |
1063 Label loop, exit; | 1063 Label loop, exit; |
1064 ForIn loop_statement(this, stmt); | 1064 ForIn loop_statement(this, stmt); |
1065 increment_loop_depth(); | 1065 increment_loop_depth(); |
1066 | 1066 |
1067 // Get the object to enumerate over. If the object is null or undefined, skip | 1067 // Get the object to enumerate over. If the object is null or undefined, skip |
1068 // over the loop. See ECMA-262 version 5, section 12.6.4. | 1068 // over the loop. See ECMA-262 version 5, section 12.6.4. |
| 1069 SetExpressionPosition(stmt->enumerable()); |
1069 VisitForAccumulatorValue(stmt->enumerable()); | 1070 VisitForAccumulatorValue(stmt->enumerable()); |
1070 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 1071 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
1071 __ cmp(r3, ip); | 1072 __ cmp(r3, ip); |
1072 __ beq(&exit); | 1073 __ beq(&exit); |
1073 Register null_value = r7; | 1074 Register null_value = r7; |
1074 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 1075 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
1075 __ cmp(r3, null_value); | 1076 __ cmp(r3, null_value); |
1076 __ beq(&exit); | 1077 __ beq(&exit); |
1077 | 1078 |
1078 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); | 1079 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 __ LoadSmiLiteral(r4, Smi::FromInt(0)); // Zero indicates proxy | 1165 __ LoadSmiLiteral(r4, Smi::FromInt(0)); // Zero indicates proxy |
1165 __ bind(&non_proxy); | 1166 __ bind(&non_proxy); |
1166 __ Push(r4, r3); // Smi and array | 1167 __ Push(r4, r3); // Smi and array |
1167 __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 1168 __ LoadP(r4, FieldMemOperand(r3, FixedArray::kLengthOffset)); |
1168 __ LoadSmiLiteral(r3, Smi::FromInt(0)); | 1169 __ LoadSmiLiteral(r3, Smi::FromInt(0)); |
1169 __ Push(r4, r3); // Fixed array length (as smi) and initial index. | 1170 __ Push(r4, r3); // Fixed array length (as smi) and initial index. |
1170 | 1171 |
1171 // Generate code for doing the condition check. | 1172 // Generate code for doing the condition check. |
1172 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 1173 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
1173 __ bind(&loop); | 1174 __ bind(&loop); |
| 1175 SetExpressionPosition(stmt->each()); |
| 1176 |
1174 // Load the current count to r3, load the length to r4. | 1177 // Load the current count to r3, load the length to r4. |
1175 __ LoadP(r3, MemOperand(sp, 0 * kPointerSize)); | 1178 __ LoadP(r3, MemOperand(sp, 0 * kPointerSize)); |
1176 __ LoadP(r4, MemOperand(sp, 1 * kPointerSize)); | 1179 __ LoadP(r4, MemOperand(sp, 1 * kPointerSize)); |
1177 __ cmpl(r3, r4); // Compare to the array length. | 1180 __ cmpl(r3, r4); // Compare to the array length. |
1178 __ bge(loop_statement.break_label()); | 1181 __ bge(loop_statement.break_label()); |
1179 | 1182 |
1180 // Get the current entry of the array into register r6. | 1183 // Get the current entry of the array into register r6. |
1181 __ LoadP(r5, MemOperand(sp, 2 * kPointerSize)); | 1184 __ LoadP(r5, MemOperand(sp, 2 * kPointerSize)); |
1182 __ addi(r5, r5, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 1185 __ addi(r5, r5, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
1183 __ SmiToPtrArrayOffset(r6, r3); | 1186 __ SmiToPtrArrayOffset(r6, r3); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1237 __ bind(loop_statement.break_label()); | 1240 __ bind(loop_statement.break_label()); |
1238 __ Drop(5); | 1241 __ Drop(5); |
1239 | 1242 |
1240 // Exit and decrement the loop depth. | 1243 // Exit and decrement the loop depth. |
1241 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | 1244 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
1242 __ bind(&exit); | 1245 __ bind(&exit); |
1243 decrement_loop_depth(); | 1246 decrement_loop_depth(); |
1244 } | 1247 } |
1245 | 1248 |
1246 | 1249 |
1247 void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | |
1248 Comment cmnt(masm_, "[ ForOfStatement"); | |
1249 SetStatementPosition(stmt); | |
1250 | |
1251 Iteration loop_statement(this, stmt); | |
1252 increment_loop_depth(); | |
1253 | |
1254 // var iterator = iterable[Symbol.iterator](); | |
1255 VisitForEffect(stmt->assign_iterator()); | |
1256 | |
1257 // Loop entry. | |
1258 __ bind(loop_statement.continue_label()); | |
1259 | |
1260 // result = iterator.next() | |
1261 VisitForEffect(stmt->next_result()); | |
1262 | |
1263 // if (result.done) break; | |
1264 Label result_not_done; | |
1265 VisitForControl(stmt->result_done(), loop_statement.break_label(), | |
1266 &result_not_done, &result_not_done); | |
1267 __ bind(&result_not_done); | |
1268 | |
1269 // each = result.value | |
1270 VisitForEffect(stmt->assign_each()); | |
1271 | |
1272 // Generate code for the body of the loop. | |
1273 Visit(stmt->body()); | |
1274 | |
1275 // Check stack before looping. | |
1276 PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); | |
1277 EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); | |
1278 __ b(loop_statement.continue_label()); | |
1279 | |
1280 // Exit and decrement the loop depth. | |
1281 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | |
1282 __ bind(loop_statement.break_label()); | |
1283 decrement_loop_depth(); | |
1284 } | |
1285 | |
1286 | |
1287 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, | 1250 void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, |
1288 bool pretenure) { | 1251 bool pretenure) { |
1289 // Use the fast case closure allocation code that allocates in new | 1252 // Use the fast case closure allocation code that allocates in new |
1290 // space for nested functions that don't need literals cloning. If | 1253 // space for nested functions that don't need literals cloning. If |
1291 // we're running with the --always-opt or the --prepare-always-opt | 1254 // we're running with the --always-opt or the --prepare-always-opt |
1292 // flag, we need to use the runtime function so that the new function | 1255 // flag, we need to use the runtime function so that the new function |
1293 // we are creating here gets a chance to have its code optimized and | 1256 // we are creating here gets a chance to have its code optimized and |
1294 // doesn't just get a copy of the existing unoptimized code. | 1257 // doesn't just get a copy of the existing unoptimized code. |
1295 if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && | 1258 if (!FLAG_always_opt && !FLAG_prepare_always_opt && !pretenure && |
1296 scope()->is_function_scope() && info->num_literals() == 0) { | 1259 scope()->is_function_scope() && info->num_literals() == 0) { |
1297 FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); | 1260 FastNewClosureStub stub(isolate(), info->language_mode(), info->kind()); |
1298 __ mov(r5, Operand(info)); | 1261 __ mov(r5, Operand(info)); |
1299 __ CallStub(&stub); | 1262 __ CallStub(&stub); |
1300 } else { | 1263 } else { |
1301 __ mov(r3, Operand(info)); | 1264 __ mov(r3, Operand(info)); |
1302 __ LoadRoot( | 1265 __ LoadRoot( |
1303 r4, pretenure ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); | 1266 r4, pretenure ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex); |
1304 __ Push(cp, r3, r4); | 1267 __ Push(cp, r3, r4); |
1305 __ CallRuntime(Runtime::kNewClosure, 3); | 1268 __ CallRuntime(Runtime::kNewClosure, 3); |
1306 } | 1269 } |
1307 context()->Plug(r3); | 1270 context()->Plug(r3); |
(...skipping 24 matching lines...) Expand all Loading... |
1332 } | 1295 } |
1333 | 1296 |
1334 __ Cmpi(r3, Operand(isolate()->factory()->undefined_value()), r0); | 1297 __ Cmpi(r3, Operand(isolate()->factory()->undefined_value()), r0); |
1335 Label done; | 1298 Label done; |
1336 __ bne(&done); | 1299 __ bne(&done); |
1337 __ CallRuntime(Runtime::kThrowNonMethodError, 0); | 1300 __ CallRuntime(Runtime::kThrowNonMethodError, 0); |
1338 __ bind(&done); | 1301 __ bind(&done); |
1339 } | 1302 } |
1340 | 1303 |
1341 | 1304 |
| 1305 void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer, |
| 1306 int offset) { |
| 1307 if (NeedsHomeObject(initializer)) { |
| 1308 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
| 1309 __ mov(StoreDescriptor::NameRegister(), |
| 1310 Operand(isolate()->factory()->home_object_symbol())); |
| 1311 __ LoadP(StoreDescriptor::ValueRegister(), |
| 1312 MemOperand(sp, offset * kPointerSize)); |
| 1313 CallStoreIC(); |
| 1314 } |
| 1315 } |
| 1316 |
| 1317 |
1342 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, | 1318 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, |
1343 TypeofState typeof_state, | 1319 TypeofState typeof_state, |
1344 Label* slow) { | 1320 Label* slow) { |
1345 Register current = cp; | 1321 Register current = cp; |
1346 Register next = r4; | 1322 Register next = r4; |
1347 Register temp = r5; | 1323 Register temp = r5; |
1348 | 1324 |
1349 Scope* s = scope(); | 1325 Scope* s = scope(); |
1350 while (s != NULL) { | 1326 while (s != NULL) { |
1351 if (s->num_heap_slots() > 0) { | 1327 if (s->num_heap_slots() > 0) { |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 // if (false) { const x; }; var y = x; | 1486 // if (false) { const x; }; var y = x; |
1511 // | 1487 // |
1512 // The condition on the declaration scopes is a conservative check for | 1488 // The condition on the declaration scopes is a conservative check for |
1513 // nested functions that access a binding and are called before the | 1489 // nested functions that access a binding and are called before the |
1514 // binding is initialized: | 1490 // binding is initialized: |
1515 // function() { f(); let x = 1; function f() { x = 2; } } | 1491 // function() { f(); let x = 1; function f() { x = 2; } } |
1516 // | 1492 // |
1517 bool skip_init_check; | 1493 bool skip_init_check; |
1518 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1494 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
1519 skip_init_check = false; | 1495 skip_init_check = false; |
| 1496 } else if (var->is_this()) { |
| 1497 CHECK(info_->function() != nullptr && |
| 1498 (info_->function()->kind() & kSubclassConstructor) != 0); |
| 1499 // TODO(dslomov): implement 'this' hole check elimination. |
| 1500 skip_init_check = false; |
1520 } else { | 1501 } else { |
1521 // Check that we always have valid source position. | 1502 // Check that we always have valid source position. |
1522 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); | 1503 DCHECK(var->initializer_position() != RelocInfo::kNoPosition); |
1523 DCHECK(proxy->position() != RelocInfo::kNoPosition); | 1504 DCHECK(proxy->position() != RelocInfo::kNoPosition); |
1524 skip_init_check = var->mode() != CONST_LEGACY && | 1505 skip_init_check = var->mode() != CONST_LEGACY && |
1525 var->initializer_position() < proxy->position(); | 1506 var->initializer_position() < proxy->position(); |
1526 } | 1507 } |
1527 | 1508 |
1528 if (!skip_init_check) { | 1509 if (!skip_init_check) { |
1529 Label done; | 1510 Label done; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1657 // If result_saved is true the result is on top of the stack. If | 1638 // If result_saved is true the result is on top of the stack. If |
1658 // result_saved is false the result is in r3. | 1639 // result_saved is false the result is in r3. |
1659 bool result_saved = false; | 1640 bool result_saved = false; |
1660 | 1641 |
1661 // Mark all computed expressions that are bound to a key that | 1642 // Mark all computed expressions that are bound to a key that |
1662 // is shadowed by a later occurrence of the same key. For the | 1643 // is shadowed by a later occurrence of the same key. For the |
1663 // marked expressions, no store code is emitted. | 1644 // marked expressions, no store code is emitted. |
1664 expr->CalculateEmitStore(zone()); | 1645 expr->CalculateEmitStore(zone()); |
1665 | 1646 |
1666 AccessorTable accessor_table(zone()); | 1647 AccessorTable accessor_table(zone()); |
1667 for (int i = 0; i < expr->properties()->length(); i++) { | 1648 int property_index = 0; |
1668 ObjectLiteral::Property* property = expr->properties()->at(i); | 1649 for (; property_index < expr->properties()->length(); property_index++) { |
| 1650 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1651 if (property->is_computed_name()) break; |
1669 if (property->IsCompileTimeValue()) continue; | 1652 if (property->IsCompileTimeValue()) continue; |
1670 | 1653 |
1671 Literal* key = property->key(); | 1654 Literal* key = property->key()->AsLiteral(); |
1672 Expression* value = property->value(); | 1655 Expression* value = property->value(); |
1673 if (!result_saved) { | 1656 if (!result_saved) { |
1674 __ push(r3); // Save result on stack | 1657 __ push(r3); // Save result on stack |
1675 result_saved = true; | 1658 result_saved = true; |
1676 } | 1659 } |
1677 switch (property->kind()) { | 1660 switch (property->kind()) { |
1678 case ObjectLiteral::Property::CONSTANT: | 1661 case ObjectLiteral::Property::CONSTANT: |
1679 UNREACHABLE(); | 1662 UNREACHABLE(); |
1680 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1663 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1681 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 1664 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
1682 // Fall through. | 1665 // Fall through. |
1683 case ObjectLiteral::Property::COMPUTED: | 1666 case ObjectLiteral::Property::COMPUTED: |
1684 // It is safe to use [[Put]] here because the boilerplate already | 1667 // It is safe to use [[Put]] here because the boilerplate already |
1685 // contains computed properties with an uninitialized value. | 1668 // contains computed properties with an uninitialized value. |
1686 if (key->value()->IsInternalizedString()) { | 1669 if (key->value()->IsInternalizedString()) { |
1687 if (property->emit_store()) { | 1670 if (property->emit_store()) { |
1688 VisitForAccumulatorValue(value); | 1671 VisitForAccumulatorValue(value); |
1689 DCHECK(StoreDescriptor::ValueRegister().is(r3)); | 1672 DCHECK(StoreDescriptor::ValueRegister().is(r3)); |
1690 __ mov(StoreDescriptor::NameRegister(), Operand(key->value())); | 1673 __ mov(StoreDescriptor::NameRegister(), Operand(key->value())); |
1691 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); | 1674 __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); |
1692 CallStoreIC(key->LiteralFeedbackId()); | 1675 CallStoreIC(key->LiteralFeedbackId()); |
1693 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1676 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
| 1677 |
| 1678 if (NeedsHomeObject(value)) { |
| 1679 __ Move(StoreDescriptor::ReceiverRegister(), r3); |
| 1680 __ mov(StoreDescriptor::NameRegister(), |
| 1681 Operand(isolate()->factory()->home_object_symbol())); |
| 1682 __ LoadP(StoreDescriptor::ValueRegister(), MemOperand(sp)); |
| 1683 CallStoreIC(); |
| 1684 } |
1694 } else { | 1685 } else { |
1695 VisitForEffect(value); | 1686 VisitForEffect(value); |
1696 } | 1687 } |
1697 break; | 1688 break; |
1698 } | 1689 } |
1699 // Duplicate receiver on stack. | 1690 // Duplicate receiver on stack. |
1700 __ LoadP(r3, MemOperand(sp)); | 1691 __ LoadP(r3, MemOperand(sp)); |
1701 __ push(r3); | 1692 __ push(r3); |
1702 VisitForStackValue(key); | 1693 VisitForStackValue(key); |
1703 VisitForStackValue(value); | 1694 VisitForStackValue(value); |
1704 if (property->emit_store()) { | 1695 if (property->emit_store()) { |
| 1696 EmitSetHomeObjectIfNeeded(value, 2); |
1705 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes | 1697 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); // PropertyAttributes |
1706 __ push(r3); | 1698 __ push(r3); |
1707 __ CallRuntime(Runtime::kSetProperty, 4); | 1699 __ CallRuntime(Runtime::kSetProperty, 4); |
1708 } else { | 1700 } else { |
1709 __ Drop(3); | 1701 __ Drop(3); |
1710 } | 1702 } |
1711 break; | 1703 break; |
1712 case ObjectLiteral::Property::PROTOTYPE: | 1704 case ObjectLiteral::Property::PROTOTYPE: |
1713 // Duplicate receiver on stack. | 1705 // Duplicate receiver on stack. |
1714 __ LoadP(r3, MemOperand(sp)); | 1706 __ LoadP(r3, MemOperand(sp)); |
(...skipping 16 matching lines...) Expand all Loading... |
1731 } | 1723 } |
1732 | 1724 |
1733 // Emit code to define accessors, using only a single call to the runtime for | 1725 // Emit code to define accessors, using only a single call to the runtime for |
1734 // each pair of corresponding getters and setters. | 1726 // each pair of corresponding getters and setters. |
1735 for (AccessorTable::Iterator it = accessor_table.begin(); | 1727 for (AccessorTable::Iterator it = accessor_table.begin(); |
1736 it != accessor_table.end(); ++it) { | 1728 it != accessor_table.end(); ++it) { |
1737 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. | 1729 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
1738 __ push(r3); | 1730 __ push(r3); |
1739 VisitForStackValue(it->first); | 1731 VisitForStackValue(it->first); |
1740 EmitAccessor(it->second->getter); | 1732 EmitAccessor(it->second->getter); |
| 1733 EmitSetHomeObjectIfNeeded(it->second->getter, 2); |
1741 EmitAccessor(it->second->setter); | 1734 EmitAccessor(it->second->setter); |
| 1735 EmitSetHomeObjectIfNeeded(it->second->setter, 3); |
1742 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); | 1736 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
1743 __ push(r3); | 1737 __ push(r3); |
1744 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); | 1738 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); |
1745 } | 1739 } |
1746 | 1740 |
| 1741 // Object literals have two parts. The "static" part on the left contains no |
| 1742 // computed property names, and so we can compute its map ahead of time; see |
| 1743 // runtime.cc::CreateObjectLiteralBoilerplate. The second "dynamic" part |
| 1744 // starts with the first computed property name, and continues with all |
| 1745 // properties to its right. All the code from above initializes the static |
| 1746 // component of the object literal, and arranges for the map of the result to |
| 1747 // reflect the static order in which the keys appear. For the dynamic |
| 1748 // properties, we compile them into a series of "SetOwnProperty" runtime |
| 1749 // calls. This will preserve insertion order. |
| 1750 for (; property_index < expr->properties()->length(); property_index++) { |
| 1751 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1752 |
| 1753 Expression* value = property->value(); |
| 1754 if (!result_saved) { |
| 1755 __ push(r3); // Save result on the stack |
| 1756 result_saved = true; |
| 1757 } |
| 1758 |
| 1759 __ LoadP(r3, MemOperand(sp)); // Duplicate receiver. |
| 1760 __ push(r3); |
| 1761 |
| 1762 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1763 DCHECK(!property->is_computed_name()); |
| 1764 VisitForStackValue(value); |
| 1765 DCHECK(property->emit_store()); |
| 1766 __ CallRuntime(Runtime::kInternalSetPrototype, 2); |
| 1767 } else { |
| 1768 EmitPropertyKey(property, expr->GetIdForProperty(property_index)); |
| 1769 VisitForStackValue(value); |
| 1770 |
| 1771 switch (property->kind()) { |
| 1772 case ObjectLiteral::Property::CONSTANT: |
| 1773 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 1774 case ObjectLiteral::Property::COMPUTED: |
| 1775 if (property->emit_store()) { |
| 1776 __ LoadSmiLiteral(r3, Smi::FromInt(NONE)); |
| 1777 __ push(r3); |
| 1778 __ CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4); |
| 1779 } else { |
| 1780 __ Drop(3); |
| 1781 } |
| 1782 break; |
| 1783 |
| 1784 case ObjectLiteral::Property::PROTOTYPE: |
| 1785 UNREACHABLE(); |
| 1786 break; |
| 1787 |
| 1788 case ObjectLiteral::Property::GETTER: |
| 1789 __ mov(r3, Operand(Smi::FromInt(NONE))); |
| 1790 __ push(r3); |
| 1791 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); |
| 1792 break; |
| 1793 |
| 1794 case ObjectLiteral::Property::SETTER: |
| 1795 __ mov(r3, Operand(Smi::FromInt(NONE))); |
| 1796 __ push(r3); |
| 1797 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); |
| 1798 break; |
| 1799 } |
| 1800 } |
| 1801 } |
| 1802 |
1747 if (expr->has_function()) { | 1803 if (expr->has_function()) { |
1748 DCHECK(result_saved); | 1804 DCHECK(result_saved); |
1749 __ LoadP(r3, MemOperand(sp)); | 1805 __ LoadP(r3, MemOperand(sp)); |
1750 __ push(r3); | 1806 __ push(r3); |
1751 __ CallRuntime(Runtime::kToFastProperties, 1); | 1807 __ CallRuntime(Runtime::kToFastProperties, 1); |
1752 } | 1808 } |
1753 | 1809 |
1754 if (result_saved) { | 1810 if (result_saved) { |
1755 context()->PlugTOS(); | 1811 context()->PlugTOS(); |
1756 } else { | 1812 } else { |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1927 EmitKeyedPropertyLoad(property); | 1983 EmitKeyedPropertyLoad(property); |
1928 PrepareForBailoutForId(property->LoadId(), TOS_REG); | 1984 PrepareForBailoutForId(property->LoadId(), TOS_REG); |
1929 break; | 1985 break; |
1930 } | 1986 } |
1931 } | 1987 } |
1932 | 1988 |
1933 Token::Value op = expr->binary_op(); | 1989 Token::Value op = expr->binary_op(); |
1934 __ push(r3); // Left operand goes on the stack. | 1990 __ push(r3); // Left operand goes on the stack. |
1935 VisitForAccumulatorValue(expr->value()); | 1991 VisitForAccumulatorValue(expr->value()); |
1936 | 1992 |
1937 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | |
1938 ? OVERWRITE_RIGHT | |
1939 : NO_OVERWRITE; | |
1940 SetSourcePosition(expr->position() + 1); | 1993 SetSourcePosition(expr->position() + 1); |
1941 AccumulatorValueContext context(this); | 1994 AccumulatorValueContext context(this); |
1942 if (ShouldInlineSmiCase(op)) { | 1995 if (ShouldInlineSmiCase(op)) { |
1943 EmitInlineSmiBinaryOp(expr->binary_operation(), op, mode, expr->target(), | 1996 EmitInlineSmiBinaryOp(expr->binary_operation(), op, expr->target(), |
1944 expr->value()); | 1997 expr->value()); |
1945 } else { | 1998 } else { |
1946 EmitBinaryOp(expr->binary_operation(), op, mode); | 1999 EmitBinaryOp(expr->binary_operation(), op); |
1947 } | 2000 } |
1948 | 2001 |
1949 // Deoptimization point in case the binary operation may have side effects. | 2002 // Deoptimization point in case the binary operation may have side effects. |
1950 PrepareForBailout(expr->binary_operation(), TOS_REG); | 2003 PrepareForBailout(expr->binary_operation(), TOS_REG); |
1951 } else { | 2004 } else { |
1952 VisitForAccumulatorValue(expr->value()); | 2005 VisitForAccumulatorValue(expr->value()); |
1953 } | 2006 } |
1954 | 2007 |
1955 // Record source position before possible IC call. | 2008 // Record source position before possible IC call. |
1956 SetSourcePosition(expr->position()); | 2009 SetSourcePosition(expr->position()); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2152 Expression* generator, Expression* value, | 2205 Expression* generator, Expression* value, |
2153 JSGeneratorObject::ResumeMode resume_mode) { | 2206 JSGeneratorObject::ResumeMode resume_mode) { |
2154 // The value stays in r3, and is ultimately read by the resumed generator, as | 2207 // The value stays in r3, and is ultimately read by the resumed generator, as |
2155 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 2208 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
2156 // is read to throw the value when the resumed generator is already closed. | 2209 // is read to throw the value when the resumed generator is already closed. |
2157 // r4 will hold the generator object until the activation has been resumed. | 2210 // r4 will hold the generator object until the activation has been resumed. |
2158 VisitForStackValue(generator); | 2211 VisitForStackValue(generator); |
2159 VisitForAccumulatorValue(value); | 2212 VisitForAccumulatorValue(value); |
2160 __ pop(r4); | 2213 __ pop(r4); |
2161 | 2214 |
2162 // Check generator state. | |
2163 Label wrong_state, closed_state, done; | |
2164 __ LoadP(r6, FieldMemOperand(r4, JSGeneratorObject::kContinuationOffset)); | |
2165 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | |
2166 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | |
2167 __ CmpSmiLiteral(r6, Smi::FromInt(0), r0); | |
2168 __ beq(&closed_state); | |
2169 __ blt(&wrong_state); | |
2170 | |
2171 // Load suspended function and context. | 2215 // Load suspended function and context. |
2172 __ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset)); | 2216 __ LoadP(cp, FieldMemOperand(r4, JSGeneratorObject::kContextOffset)); |
2173 __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset)); | 2217 __ LoadP(r7, FieldMemOperand(r4, JSGeneratorObject::kFunctionOffset)); |
2174 | 2218 |
2175 // Load receiver and store as the first argument. | 2219 // Load receiver and store as the first argument. |
2176 __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset)); | 2220 __ LoadP(r5, FieldMemOperand(r4, JSGeneratorObject::kReceiverOffset)); |
2177 __ push(r5); | 2221 __ push(r5); |
2178 | 2222 |
2179 // Push holes for the rest of the arguments to the generator function. | 2223 // Push holes for the rest of the arguments to the generator function. |
2180 __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset)); | 2224 __ LoadP(r6, FieldMemOperand(r7, JSFunction::kSharedFunctionInfoOffset)); |
2181 __ LoadWordArith( | 2225 __ LoadWordArith( |
2182 r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset)); | 2226 r6, FieldMemOperand(r6, SharedFunctionInfo::kFormalParameterCountOffset)); |
2183 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); | 2227 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); |
2184 Label argument_loop, push_frame; | 2228 Label argument_loop, push_frame; |
2185 #if V8_TARGET_ARCH_PPC64 | 2229 #if V8_TARGET_ARCH_PPC64 |
2186 __ cmpi(r6, Operand::Zero()); | 2230 __ cmpi(r6, Operand::Zero()); |
2187 __ beq(&push_frame); | 2231 __ beq(&push_frame); |
2188 #else | 2232 #else |
2189 __ SmiUntag(r6, SetRC); | 2233 __ SmiUntag(r6, SetRC); |
2190 __ beq(&push_frame, cr0); | 2234 __ beq(&push_frame, cr0); |
2191 #endif | 2235 #endif |
2192 __ mtctr(r6); | 2236 __ mtctr(r6); |
2193 __ bind(&argument_loop); | 2237 __ bind(&argument_loop); |
2194 __ push(r5); | 2238 __ push(r5); |
2195 __ bdnz(&argument_loop); | 2239 __ bdnz(&argument_loop); |
2196 | 2240 |
2197 // Enter a new JavaScript frame, and initialize its slots as they were when | 2241 // Enter a new JavaScript frame, and initialize its slots as they were when |
2198 // the generator was suspended. | 2242 // the generator was suspended. |
2199 Label resume_frame; | 2243 Label resume_frame, done; |
2200 __ bind(&push_frame); | 2244 __ bind(&push_frame); |
2201 __ b(&resume_frame, SetLK); | 2245 __ b(&resume_frame, SetLK); |
2202 __ b(&done); | 2246 __ b(&done); |
2203 __ bind(&resume_frame); | 2247 __ bind(&resume_frame); |
2204 // lr = return address. | 2248 // lr = return address. |
2205 // fp = caller's frame pointer. | 2249 // fp = caller's frame pointer. |
2206 // cp = callee's context, | 2250 // cp = callee's context, |
2207 // r7 = callee's JS function. | 2251 // r7 = callee's JS function. |
2208 __ PushFixedFrame(r7); | 2252 __ PushFixedFrame(r7); |
2209 // Adjust FP to point to saved FP. | 2253 // Adjust FP to point to saved FP. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2253 __ bdnz(&operand_loop); | 2297 __ bdnz(&operand_loop); |
2254 | 2298 |
2255 __ bind(&call_resume); | 2299 __ bind(&call_resume); |
2256 DCHECK(!result_register().is(r4)); | 2300 DCHECK(!result_register().is(r4)); |
2257 __ Push(r4, result_register()); | 2301 __ Push(r4, result_register()); |
2258 __ Push(Smi::FromInt(resume_mode)); | 2302 __ Push(Smi::FromInt(resume_mode)); |
2259 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2303 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
2260 // Not reached: the runtime call returns elsewhere. | 2304 // Not reached: the runtime call returns elsewhere. |
2261 __ stop("not-reached"); | 2305 __ stop("not-reached"); |
2262 | 2306 |
2263 // Reach here when generator is closed. | |
2264 __ bind(&closed_state); | |
2265 if (resume_mode == JSGeneratorObject::NEXT) { | |
2266 // Return completed iterator result when generator is closed. | |
2267 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | |
2268 __ push(r5); | |
2269 // Pop value from top-of-stack slot; box result into result register. | |
2270 EmitCreateIteratorResult(true); | |
2271 } else { | |
2272 // Throw the provided value. | |
2273 __ push(r3); | |
2274 __ CallRuntime(Runtime::kThrow, 1); | |
2275 } | |
2276 __ b(&done); | |
2277 | |
2278 // Throw error if we attempt to operate on a running generator. | |
2279 __ bind(&wrong_state); | |
2280 __ push(r4); | |
2281 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | |
2282 | |
2283 __ bind(&done); | 2307 __ bind(&done); |
2284 context()->Plug(result_register()); | 2308 context()->Plug(result_register()); |
2285 } | 2309 } |
2286 | 2310 |
2287 | 2311 |
2288 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { | 2312 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
2289 Label gc_required; | 2313 Label gc_required; |
2290 Label allocated; | 2314 Label allocated; |
2291 | 2315 |
2292 const int instance_size = 5 * kPointerSize; | 2316 const int instance_size = 5 * kPointerSize; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2370 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { | 2394 void FullCodeGenerator::EmitKeyedSuperPropertyLoad(Property* prop) { |
2371 // Stack: receiver, home_object, key. | 2395 // Stack: receiver, home_object, key. |
2372 SetSourcePosition(prop->position()); | 2396 SetSourcePosition(prop->position()); |
2373 | 2397 |
2374 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); | 2398 __ CallRuntime(Runtime::kLoadKeyedFromSuper, 3); |
2375 } | 2399 } |
2376 | 2400 |
2377 | 2401 |
2378 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, | 2402 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, |
2379 Token::Value op, | 2403 Token::Value op, |
2380 OverwriteMode mode, | |
2381 Expression* left_expr, | 2404 Expression* left_expr, |
2382 Expression* right_expr) { | 2405 Expression* right_expr) { |
2383 Label done, smi_case, stub_call; | 2406 Label done, smi_case, stub_call; |
2384 | 2407 |
2385 Register scratch1 = r5; | 2408 Register scratch1 = r5; |
2386 Register scratch2 = r6; | 2409 Register scratch2 = r6; |
2387 | 2410 |
2388 // Get the arguments. | 2411 // Get the arguments. |
2389 Register left = r4; | 2412 Register left = r4; |
2390 Register right = r3; | 2413 Register right = r3; |
2391 __ pop(left); | 2414 __ pop(left); |
2392 | 2415 |
2393 // Perform combined smi check on both operands. | 2416 // Perform combined smi check on both operands. |
2394 __ orx(scratch1, left, right); | 2417 __ orx(scratch1, left, right); |
2395 STATIC_ASSERT(kSmiTag == 0); | 2418 STATIC_ASSERT(kSmiTag == 0); |
2396 JumpPatchSite patch_site(masm_); | 2419 JumpPatchSite patch_site(masm_); |
2397 patch_site.EmitJumpIfSmi(scratch1, &smi_case); | 2420 patch_site.EmitJumpIfSmi(scratch1, &smi_case); |
2398 | 2421 |
2399 __ bind(&stub_call); | 2422 __ bind(&stub_call); |
2400 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); | 2423 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
2401 CallIC(code, expr->BinaryOperationFeedbackId()); | 2424 CallIC(code, expr->BinaryOperationFeedbackId()); |
2402 patch_site.EmitPatchInfo(); | 2425 patch_site.EmitPatchInfo(); |
2403 __ b(&done); | 2426 __ b(&done); |
2404 | 2427 |
2405 __ bind(&smi_case); | 2428 __ bind(&smi_case); |
2406 // Smi case. This code works the same way as the smi-smi case in the type | 2429 // Smi case. This code works the same way as the smi-smi case in the type |
2407 // recording binary operation stub. | 2430 // recording binary operation stub. |
2408 switch (op) { | 2431 switch (op) { |
2409 case Token::SAR: | 2432 case Token::SAR: |
2410 __ GetLeastBitsFromSmi(scratch1, right, 5); | 2433 __ GetLeastBitsFromSmi(scratch1, right, 5); |
(...skipping 17 matching lines...) Expand all Loading... |
2428 __ SmiUntag(scratch1, left); | 2451 __ SmiUntag(scratch1, left); |
2429 __ GetLeastBitsFromSmi(scratch2, right, 5); | 2452 __ GetLeastBitsFromSmi(scratch2, right, 5); |
2430 __ srw(scratch1, scratch1, scratch2); | 2453 __ srw(scratch1, scratch1, scratch2); |
2431 // Unsigned shift is not allowed to produce a negative number. | 2454 // Unsigned shift is not allowed to produce a negative number. |
2432 __ JumpIfNotUnsignedSmiCandidate(scratch1, r0, &stub_call); | 2455 __ JumpIfNotUnsignedSmiCandidate(scratch1, r0, &stub_call); |
2433 __ SmiTag(right, scratch1); | 2456 __ SmiTag(right, scratch1); |
2434 break; | 2457 break; |
2435 } | 2458 } |
2436 case Token::ADD: { | 2459 case Token::ADD: { |
2437 __ AddAndCheckForOverflow(scratch1, left, right, scratch2, r0); | 2460 __ AddAndCheckForOverflow(scratch1, left, right, scratch2, r0); |
2438 __ bne(&stub_call, cr0); | 2461 __ BranchOnOverflow(&stub_call); |
2439 __ mr(right, scratch1); | 2462 __ mr(right, scratch1); |
2440 break; | 2463 break; |
2441 } | 2464 } |
2442 case Token::SUB: { | 2465 case Token::SUB: { |
2443 __ SubAndCheckForOverflow(scratch1, left, right, scratch2, r0); | 2466 __ SubAndCheckForOverflow(scratch1, left, right, scratch2, r0); |
2444 __ bne(&stub_call, cr0); | 2467 __ BranchOnOverflow(&stub_call); |
2445 __ mr(right, scratch1); | 2468 __ mr(right, scratch1); |
2446 break; | 2469 break; |
2447 } | 2470 } |
2448 case Token::MUL: { | 2471 case Token::MUL: { |
2449 Label mul_zero; | 2472 Label mul_zero; |
2450 #if V8_TARGET_ARCH_PPC64 | 2473 #if V8_TARGET_ARCH_PPC64 |
2451 // Remove tag from both operands. | 2474 // Remove tag from both operands. |
2452 __ SmiUntag(ip, right); | 2475 __ SmiUntag(ip, right); |
2453 __ SmiUntag(r0, left); | 2476 __ SmiUntag(r0, left); |
2454 __ Mul(scratch1, r0, ip); | 2477 __ Mul(scratch1, r0, ip); |
2455 // Check for overflowing the smi range - no overflow if higher 33 bits of | 2478 // Check for overflowing the smi range - no overflow if higher 33 bits of |
2456 // the result are identical. | 2479 // the result are identical. |
2457 __ TestIfInt32(scratch1, scratch2, ip); | 2480 __ TestIfInt32(scratch1, r0); |
2458 __ bne(&stub_call); | 2481 __ bne(&stub_call); |
2459 #else | 2482 #else |
2460 __ SmiUntag(ip, right); | 2483 __ SmiUntag(ip, right); |
2461 __ mullw(scratch1, left, ip); | 2484 __ mullw(scratch1, left, ip); |
2462 __ mulhw(scratch2, left, ip); | 2485 __ mulhw(scratch2, left, ip); |
2463 // Check for overflowing the smi range - no overflow if higher 33 bits of | 2486 // Check for overflowing the smi range - no overflow if higher 33 bits of |
2464 // the result are identical. | 2487 // the result are identical. |
2465 __ TestIfInt32(scratch2, scratch1, ip); | 2488 __ TestIfInt32(scratch2, scratch1, ip); |
2466 __ bne(&stub_call); | 2489 __ bne(&stub_call); |
2467 #endif | 2490 #endif |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 | 2531 |
2509 // No access check is needed here since the constructor is created by the | 2532 // No access check is needed here since the constructor is created by the |
2510 // class literal. | 2533 // class literal. |
2511 Register scratch = r4; | 2534 Register scratch = r4; |
2512 __ LoadP(scratch, | 2535 __ LoadP(scratch, |
2513 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset)); | 2536 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset)); |
2514 __ push(scratch); | 2537 __ push(scratch); |
2515 | 2538 |
2516 for (int i = 0; i < lit->properties()->length(); i++) { | 2539 for (int i = 0; i < lit->properties()->length(); i++) { |
2517 ObjectLiteral::Property* property = lit->properties()->at(i); | 2540 ObjectLiteral::Property* property = lit->properties()->at(i); |
2518 Literal* key = property->key()->AsLiteral(); | |
2519 Expression* value = property->value(); | 2541 Expression* value = property->value(); |
2520 DCHECK(key != NULL); | |
2521 | 2542 |
2522 if (property->is_static()) { | 2543 if (property->is_static()) { |
2523 __ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor | 2544 __ LoadP(scratch, MemOperand(sp, kPointerSize)); // constructor |
2524 } else { | 2545 } else { |
2525 __ LoadP(scratch, MemOperand(sp, 0)); // prototype | 2546 __ LoadP(scratch, MemOperand(sp, 0)); // prototype |
2526 } | 2547 } |
2527 __ push(scratch); | 2548 __ push(scratch); |
2528 VisitForStackValue(key); | 2549 EmitPropertyKey(property, lit->GetIdForProperty(i)); |
2529 VisitForStackValue(value); | 2550 VisitForStackValue(value); |
| 2551 EmitSetHomeObjectIfNeeded(value, 2); |
2530 | 2552 |
2531 switch (property->kind()) { | 2553 switch (property->kind()) { |
2532 case ObjectLiteral::Property::CONSTANT: | 2554 case ObjectLiteral::Property::CONSTANT: |
2533 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2555 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
2534 case ObjectLiteral::Property::PROTOTYPE: | 2556 case ObjectLiteral::Property::PROTOTYPE: |
2535 UNREACHABLE(); | 2557 UNREACHABLE(); |
2536 case ObjectLiteral::Property::COMPUTED: | 2558 case ObjectLiteral::Property::COMPUTED: |
2537 __ CallRuntime(Runtime::kDefineClassMethod, 3); | 2559 __ CallRuntime(Runtime::kDefineClassMethod, 3); |
2538 break; | 2560 break; |
2539 | 2561 |
2540 case ObjectLiteral::Property::GETTER: | 2562 case ObjectLiteral::Property::GETTER: |
2541 __ CallRuntime(Runtime::kDefineClassGetter, 3); | 2563 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
| 2564 __ push(r3); |
| 2565 __ CallRuntime(Runtime::kDefineGetterPropertyUnchecked, 4); |
2542 break; | 2566 break; |
2543 | 2567 |
2544 case ObjectLiteral::Property::SETTER: | 2568 case ObjectLiteral::Property::SETTER: |
2545 __ CallRuntime(Runtime::kDefineClassSetter, 3); | 2569 __ mov(r3, Operand(Smi::FromInt(DONT_ENUM))); |
| 2570 __ push(r3); |
| 2571 __ CallRuntime(Runtime::kDefineSetterPropertyUnchecked, 4); |
2546 break; | 2572 break; |
2547 | 2573 |
2548 default: | 2574 default: |
2549 UNREACHABLE(); | 2575 UNREACHABLE(); |
2550 } | 2576 } |
2551 } | 2577 } |
2552 | 2578 |
2553 // prototype | 2579 // prototype |
2554 __ CallRuntime(Runtime::kToFastProperties, 1); | 2580 __ CallRuntime(Runtime::kToFastProperties, 1); |
2555 | 2581 |
2556 // constructor | 2582 // constructor |
2557 __ CallRuntime(Runtime::kToFastProperties, 1); | 2583 __ CallRuntime(Runtime::kToFastProperties, 1); |
2558 } | 2584 } |
2559 | 2585 |
2560 | 2586 |
2561 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op, | 2587 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { |
2562 OverwriteMode mode) { | |
2563 __ pop(r4); | 2588 __ pop(r4); |
2564 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); | 2589 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code(); |
2565 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. | 2590 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. |
2566 CallIC(code, expr->BinaryOperationFeedbackId()); | 2591 CallIC(code, expr->BinaryOperationFeedbackId()); |
2567 patch_site.EmitPatchInfo(); | 2592 patch_site.EmitPatchInfo(); |
2568 context()->Plug(r3); | 2593 context()->Plug(r3); |
2569 } | 2594 } |
2570 | 2595 |
2571 | 2596 |
2572 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 2597 void FullCodeGenerator::EmitAssignment(Expression* expr) { |
2573 DCHECK(expr->IsValidReferenceExpression()); | 2598 DCHECK(expr->IsValidReferenceExpression()); |
2574 | 2599 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2629 break; | 2654 break; |
2630 } | 2655 } |
2631 case KEYED_PROPERTY: { | 2656 case KEYED_PROPERTY: { |
2632 __ push(r3); // Preserve value. | 2657 __ push(r3); // Preserve value. |
2633 VisitForStackValue(prop->obj()); | 2658 VisitForStackValue(prop->obj()); |
2634 VisitForAccumulatorValue(prop->key()); | 2659 VisitForAccumulatorValue(prop->key()); |
2635 __ Move(StoreDescriptor::NameRegister(), r3); | 2660 __ Move(StoreDescriptor::NameRegister(), r3); |
2636 __ Pop(StoreDescriptor::ValueRegister(), | 2661 __ Pop(StoreDescriptor::ValueRegister(), |
2637 StoreDescriptor::ReceiverRegister()); | 2662 StoreDescriptor::ReceiverRegister()); |
2638 Handle<Code> ic = | 2663 Handle<Code> ic = |
2639 CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); | 2664 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
2640 CallIC(ic); | 2665 CallIC(ic); |
2641 break; | 2666 break; |
2642 } | 2667 } |
2643 } | 2668 } |
2644 context()->Plug(r3); | 2669 context()->Plug(r3); |
2645 } | 2670 } |
2646 | 2671 |
2647 | 2672 |
2648 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( | 2673 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
2649 Variable* var, MemOperand location) { | 2674 Variable* var, MemOperand location) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2698 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2723 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
2699 // Perform the assignment. | 2724 // Perform the assignment. |
2700 __ bind(&assign); | 2725 __ bind(&assign); |
2701 EmitStoreToStackLocalOrContextSlot(var, location); | 2726 EmitStoreToStackLocalOrContextSlot(var, location); |
2702 | 2727 |
2703 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { | 2728 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
2704 if (var->IsLookupSlot()) { | 2729 if (var->IsLookupSlot()) { |
2705 // Assignment to var. | 2730 // Assignment to var. |
2706 __ push(r3); // Value. | 2731 __ push(r3); // Value. |
2707 __ mov(r4, Operand(var->name())); | 2732 __ mov(r4, Operand(var->name())); |
2708 __ mov(r3, Operand(Smi::FromInt(strict_mode()))); | 2733 __ mov(r3, Operand(Smi::FromInt(language_mode()))); |
2709 __ Push(cp, r4, r3); // Context, name, strict mode. | 2734 __ Push(cp, r4, r3); // Context, name, language mode. |
2710 __ CallRuntime(Runtime::kStoreLookupSlot, 4); | 2735 __ CallRuntime(Runtime::kStoreLookupSlot, 4); |
2711 } else { | 2736 } else { |
2712 // Assignment to var or initializing assignment to let/const in harmony | 2737 // Assignment to var or initializing assignment to let/const in harmony |
2713 // mode. | 2738 // mode. |
2714 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2739 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
2715 MemOperand location = VarOperand(var, r4); | 2740 MemOperand location = VarOperand(var, r4); |
2716 if (generate_debug_code_ && op == Token::INIT_LET) { | 2741 if (generate_debug_code_ && op == Token::INIT_LET) { |
2717 // Check for an uninitialized let binding. | 2742 // Check for an uninitialized let binding. |
2718 __ LoadP(r5, location); | 2743 __ LoadP(r5, location); |
2719 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2744 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
2720 __ Check(eq, kLetBindingReInitialization); | 2745 __ Check(eq, kLetBindingReInitialization); |
2721 } | 2746 } |
2722 EmitStoreToStackLocalOrContextSlot(var, location); | 2747 EmitStoreToStackLocalOrContextSlot(var, location); |
2723 } | 2748 } |
| 2749 } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { |
| 2750 __ CallRuntime(Runtime::kThrowConstAssignError, 0); |
2724 } | 2751 } |
2725 // Non-initializing assignments to consts are ignored. | |
2726 } | 2752 } |
2727 | 2753 |
2728 | 2754 |
2729 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 2755 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
2730 // Assignment to a property, using a named store IC. | 2756 // Assignment to a property, using a named store IC. |
2731 Property* prop = expr->target()->AsProperty(); | 2757 Property* prop = expr->target()->AsProperty(); |
2732 DCHECK(prop != NULL); | 2758 DCHECK(prop != NULL); |
2733 DCHECK(prop->key()->IsLiteral()); | 2759 DCHECK(prop->key()->IsLiteral()); |
2734 | 2760 |
2735 // Record source code position before IC call. | 2761 // Record source code position before IC call. |
(...skipping 11 matching lines...) Expand all Loading... |
2747 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { | 2773 void FullCodeGenerator::EmitNamedSuperPropertyStore(Property* prop) { |
2748 // Assignment to named property of super. | 2774 // Assignment to named property of super. |
2749 // r3 : value | 2775 // r3 : value |
2750 // stack : receiver ('this'), home_object | 2776 // stack : receiver ('this'), home_object |
2751 DCHECK(prop != NULL); | 2777 DCHECK(prop != NULL); |
2752 Literal* key = prop->key()->AsLiteral(); | 2778 Literal* key = prop->key()->AsLiteral(); |
2753 DCHECK(key != NULL); | 2779 DCHECK(key != NULL); |
2754 | 2780 |
2755 __ Push(key->value()); | 2781 __ Push(key->value()); |
2756 __ Push(r3); | 2782 __ Push(r3); |
2757 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreToSuper_Strict | 2783 __ CallRuntime((is_strict(language_mode()) ? Runtime::kStoreToSuper_Strict |
2758 : Runtime::kStoreToSuper_Sloppy), | 2784 : Runtime::kStoreToSuper_Sloppy), |
2759 4); | 2785 4); |
2760 } | 2786 } |
2761 | 2787 |
2762 | 2788 |
2763 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { | 2789 void FullCodeGenerator::EmitKeyedSuperPropertyStore(Property* prop) { |
2764 // Assignment to named property of super. | 2790 // Assignment to named property of super. |
2765 // r3 : value | 2791 // r3 : value |
2766 // stack : receiver ('this'), home_object, key | 2792 // stack : receiver ('this'), home_object, key |
2767 DCHECK(prop != NULL); | 2793 DCHECK(prop != NULL); |
2768 | 2794 |
2769 __ Push(r3); | 2795 __ Push(r3); |
2770 __ CallRuntime((strict_mode() == STRICT ? Runtime::kStoreKeyedToSuper_Strict | 2796 __ CallRuntime( |
2771 : Runtime::kStoreKeyedToSuper_Sloppy), | 2797 (is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
2772 4); | 2798 : Runtime::kStoreKeyedToSuper_Sloppy), |
| 2799 4); |
2773 } | 2800 } |
2774 | 2801 |
2775 | 2802 |
2776 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2803 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
2777 // Assignment to a property, using a keyed store IC. | 2804 // Assignment to a property, using a keyed store IC. |
2778 | 2805 |
2779 // Record source code position before IC call. | 2806 // Record source code position before IC call. |
2780 SetSourcePosition(expr->position()); | 2807 SetSourcePosition(expr->position()); |
2781 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); | 2808 __ Pop(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister()); |
2782 DCHECK(StoreDescriptor::ValueRegister().is(r3)); | 2809 DCHECK(StoreDescriptor::ValueRegister().is(r3)); |
2783 | 2810 |
2784 Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); | 2811 Handle<Code> ic = |
| 2812 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
2785 CallIC(ic, expr->AssignmentFeedbackId()); | 2813 CallIC(ic, expr->AssignmentFeedbackId()); |
2786 | 2814 |
2787 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2815 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
2788 context()->Plug(r3); | 2816 context()->Plug(r3); |
2789 } | 2817 } |
2790 | 2818 |
2791 | 2819 |
2792 void FullCodeGenerator::VisitProperty(Property* expr) { | 2820 void FullCodeGenerator::VisitProperty(Property* expr) { |
2793 Comment cmnt(masm_, "[ Property"); | 2821 Comment cmnt(masm_, "[ Property"); |
2794 Expression* key = expr->key(); | 2822 Expression* key = expr->key(); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2966 int arg_count = args->length(); | 2994 int arg_count = args->length(); |
2967 { | 2995 { |
2968 PreservePositionScope scope(masm()->positions_recorder()); | 2996 PreservePositionScope scope(masm()->positions_recorder()); |
2969 for (int i = 0; i < arg_count; i++) { | 2997 for (int i = 0; i < arg_count; i++) { |
2970 VisitForStackValue(args->at(i)); | 2998 VisitForStackValue(args->at(i)); |
2971 } | 2999 } |
2972 } | 3000 } |
2973 | 3001 |
2974 // Record source position of the IC call. | 3002 // Record source position of the IC call. |
2975 SetSourcePosition(expr->position()); | 3003 SetSourcePosition(expr->position()); |
2976 Handle<Code> ic = CallIC::initialize_stub(isolate(), arg_count, call_type); | 3004 Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code(); |
2977 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackSlot())); | 3005 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackICSlot())); |
2978 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); | 3006 __ LoadP(r4, MemOperand(sp, (arg_count + 1) * kPointerSize), r0); |
2979 // Don't assign a type feedback id to the IC, since type feedback is provided | 3007 // Don't assign a type feedback id to the IC, since type feedback is provided |
2980 // by the vector above. | 3008 // by the vector above. |
2981 CallIC(ic); | 3009 CallIC(ic); |
2982 | 3010 |
2983 RecordJSReturnSite(expr); | 3011 RecordJSReturnSite(expr); |
2984 // Restore context register. | 3012 // Restore context register. |
2985 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3013 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2986 context()->DropAndPlug(1, r3); | 3014 context()->DropAndPlug(1, r3); |
2987 } | 3015 } |
2988 | 3016 |
2989 | 3017 |
2990 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 3018 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
2991 // r8: copy of the first argument or undefined if it doesn't exist. | 3019 // r8: copy of the first argument or undefined if it doesn't exist. |
2992 if (arg_count > 0) { | 3020 if (arg_count > 0) { |
2993 __ LoadP(r8, MemOperand(sp, arg_count * kPointerSize), r0); | 3021 __ LoadP(r8, MemOperand(sp, arg_count * kPointerSize), r0); |
2994 } else { | 3022 } else { |
2995 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 3023 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
2996 } | 3024 } |
2997 | 3025 |
2998 // r7: the receiver of the enclosing function. | 3026 // r7: the receiver of the enclosing function. |
2999 __ LoadP(r7, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3027 __ LoadP(r7, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
3000 | 3028 |
3001 // r6: the receiver of the enclosing function. | 3029 // r6: the receiver of the enclosing function. |
3002 int receiver_offset = 2 + info_->scope()->num_parameters(); | 3030 int receiver_offset = 2 + info_->scope()->num_parameters(); |
3003 __ LoadP(r6, MemOperand(fp, receiver_offset * kPointerSize), r0); | 3031 __ LoadP(r6, MemOperand(fp, receiver_offset * kPointerSize), r0); |
3004 | 3032 |
3005 // r5: strict mode. | 3033 // r5: language mode. |
3006 __ LoadSmiLiteral(r5, Smi::FromInt(strict_mode())); | 3034 __ LoadSmiLiteral(r5, Smi::FromInt(language_mode())); |
3007 | 3035 |
3008 // r4: the start position of the scope the calls resides in. | 3036 // r4: the start position of the scope the calls resides in. |
3009 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); | 3037 __ LoadSmiLiteral(r4, Smi::FromInt(scope()->start_position())); |
3010 | 3038 |
3011 // Do the runtime call. | 3039 // Do the runtime call. |
3012 __ Push(r8, r7, r6, r5, r4); | 3040 __ Push(r8, r7, r6, r5, r4); |
3013 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); | 3041 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); |
3014 } | 3042 } |
3015 | 3043 |
3016 | 3044 |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3133 PreservePositionScope scope(masm()->positions_recorder()); | 3161 PreservePositionScope scope(masm()->positions_recorder()); |
3134 VisitForStackValue(property->obj()); | 3162 VisitForStackValue(property->obj()); |
3135 } | 3163 } |
3136 if (is_named_call) { | 3164 if (is_named_call) { |
3137 EmitCallWithLoadIC(expr); | 3165 EmitCallWithLoadIC(expr); |
3138 } else { | 3166 } else { |
3139 EmitKeyedCallWithLoadIC(expr, property->key()); | 3167 EmitKeyedCallWithLoadIC(expr, property->key()); |
3140 } | 3168 } |
3141 } | 3169 } |
3142 } else if (call_type == Call::SUPER_CALL) { | 3170 } else if (call_type == Call::SUPER_CALL) { |
3143 SuperReference* super_ref = callee->AsSuperReference(); | 3171 if (FLAG_experimental_classes) { |
3144 EmitLoadSuperConstructor(super_ref); | 3172 EmitSuperConstructorCall(expr); |
3145 __ Push(result_register()); | 3173 } else { |
3146 VisitForStackValue(super_ref->this_var()); | 3174 SuperReference* super_ref = callee->AsSuperReference(); |
3147 EmitCall(expr, CallICState::METHOD); | 3175 EmitLoadSuperConstructor(super_ref); |
| 3176 __ Push(result_register()); |
| 3177 VisitForStackValue(super_ref->this_var()); |
| 3178 EmitCall(expr, CallICState::METHOD); |
| 3179 } |
3148 } else { | 3180 } else { |
3149 DCHECK(call_type == Call::OTHER_CALL); | 3181 DCHECK(call_type == Call::OTHER_CALL); |
3150 // Call to an arbitrary expression not handled specially above. | 3182 // Call to an arbitrary expression not handled specially above. |
3151 { | 3183 { |
3152 PreservePositionScope scope(masm()->positions_recorder()); | 3184 PreservePositionScope scope(masm()->positions_recorder()); |
3153 VisitForStackValue(callee); | 3185 VisitForStackValue(callee); |
3154 } | 3186 } |
3155 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 3187 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
3156 __ push(r4); | 3188 __ push(r4); |
3157 // Emit function call. | 3189 // Emit function call. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3206 __ Move(r5, FeedbackVector()); | 3238 __ Move(r5, FeedbackVector()); |
3207 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallNewFeedbackSlot())); | 3239 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallNewFeedbackSlot())); |
3208 | 3240 |
3209 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); | 3241 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
3210 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); | 3242 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
3211 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 3243 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
3212 context()->Plug(r3); | 3244 context()->Plug(r3); |
3213 } | 3245 } |
3214 | 3246 |
3215 | 3247 |
| 3248 void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) { |
| 3249 SuperReference* super_ref = expr->expression()->AsSuperReference(); |
| 3250 EmitLoadSuperConstructor(super_ref); |
| 3251 __ push(result_register()); |
| 3252 |
| 3253 Variable* this_var = super_ref->this_var()->var(); |
| 3254 |
| 3255 GetVar(r3, this_var); |
| 3256 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 3257 Label uninitialized_this; |
| 3258 __ beq(&uninitialized_this); |
| 3259 __ mov(r3, Operand(this_var->name())); |
| 3260 __ push(r3); |
| 3261 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 3262 __ bind(&uninitialized_this); |
| 3263 |
| 3264 // Push the arguments ("left-to-right") on the stack. |
| 3265 ZoneList<Expression*>* args = expr->arguments(); |
| 3266 int arg_count = args->length(); |
| 3267 for (int i = 0; i < arg_count; i++) { |
| 3268 VisitForStackValue(args->at(i)); |
| 3269 } |
| 3270 |
| 3271 // Call the construct call builtin that handles allocation and |
| 3272 // constructor invocation. |
| 3273 SetSourcePosition(expr->position()); |
| 3274 |
| 3275 // Load function and argument count into r1 and r0. |
| 3276 __ mov(r3, Operand(arg_count)); |
| 3277 __ LoadP(r4, MemOperand(sp, arg_count * kPointerSize)); |
| 3278 |
| 3279 // Record call targets in unoptimized code. |
| 3280 if (FLAG_pretenuring_call_new) { |
| 3281 UNREACHABLE(); |
| 3282 /* TODO(dslomov): support pretenuring. |
| 3283 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); |
| 3284 DCHECK(expr->AllocationSiteFeedbackSlot().ToInt() == |
| 3285 expr->CallNewFeedbackSlot().ToInt() + 1); |
| 3286 */ |
| 3287 } |
| 3288 |
| 3289 __ Move(r5, FeedbackVector()); |
| 3290 __ LoadSmiLiteral(r6, SmiFromSlot(expr->CallFeedbackSlot())); |
| 3291 |
| 3292 // TODO(dslomov): use a different stub and propagate new.target. |
| 3293 CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); |
| 3294 __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); |
| 3295 |
| 3296 RecordJSReturnSite(expr); |
| 3297 |
| 3298 EmitVariableAssignment(this_var, Token::INIT_CONST); |
| 3299 context()->Plug(r3); |
| 3300 } |
| 3301 |
| 3302 |
3216 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { | 3303 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { |
3217 ZoneList<Expression*>* args = expr->arguments(); | 3304 ZoneList<Expression*>* args = expr->arguments(); |
3218 DCHECK(args->length() == 1); | 3305 DCHECK(args->length() == 1); |
3219 | 3306 |
3220 VisitForAccumulatorValue(args->at(0)); | 3307 VisitForAccumulatorValue(args->at(0)); |
3221 | 3308 |
3222 Label materialize_true, materialize_false; | 3309 Label materialize_true, materialize_false; |
3223 Label* if_true = NULL; | 3310 Label* if_true = NULL; |
3224 Label* if_false = NULL; | 3311 Label* if_false = NULL; |
3225 Label* fall_through = NULL; | 3312 Label* fall_through = NULL; |
(...skipping 1279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4505 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4592 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
4506 switch (expr->op()) { | 4593 switch (expr->op()) { |
4507 case Token::DELETE: { | 4594 case Token::DELETE: { |
4508 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4595 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
4509 Property* property = expr->expression()->AsProperty(); | 4596 Property* property = expr->expression()->AsProperty(); |
4510 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4597 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
4511 | 4598 |
4512 if (property != NULL) { | 4599 if (property != NULL) { |
4513 VisitForStackValue(property->obj()); | 4600 VisitForStackValue(property->obj()); |
4514 VisitForStackValue(property->key()); | 4601 VisitForStackValue(property->key()); |
4515 __ LoadSmiLiteral(r4, Smi::FromInt(strict_mode())); | 4602 __ LoadSmiLiteral(r4, Smi::FromInt(language_mode())); |
4516 __ push(r4); | 4603 __ push(r4); |
4517 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4604 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4518 context()->Plug(r3); | 4605 context()->Plug(r3); |
4519 } else if (proxy != NULL) { | 4606 } else if (proxy != NULL) { |
4520 Variable* var = proxy->var(); | 4607 Variable* var = proxy->var(); |
4521 // Delete of an unqualified identifier is disallowed in strict mode | 4608 // Delete of an unqualified identifier is disallowed in strict mode |
4522 // but "delete this" is allowed. | 4609 // but "delete this" is allowed. |
4523 DCHECK(strict_mode() == SLOPPY || var->is_this()); | 4610 DCHECK(is_sloppy(language_mode()) || var->is_this()); |
4524 if (var->IsUnallocated()) { | 4611 if (var->IsUnallocated()) { |
4525 __ LoadP(r5, GlobalObjectOperand()); | 4612 __ LoadP(r5, GlobalObjectOperand()); |
4526 __ mov(r4, Operand(var->name())); | 4613 __ mov(r4, Operand(var->name())); |
4527 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); | 4614 __ LoadSmiLiteral(r3, Smi::FromInt(SLOPPY)); |
4528 __ Push(r5, r4, r3); | 4615 __ Push(r5, r4, r3); |
4529 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4616 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
4530 context()->Plug(r3); | 4617 context()->Plug(r3); |
4531 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4618 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
4532 // Result of deleting non-global, non-dynamic variables is false. | 4619 // Result of deleting non-global, non-dynamic variables is false. |
4533 // The subexpression does not have side effects. | 4620 // The subexpression does not have side effects. |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4761 } | 4848 } |
4762 } | 4849 } |
4763 | 4850 |
4764 __ bind(&stub_call); | 4851 __ bind(&stub_call); |
4765 __ mr(r4, r3); | 4852 __ mr(r4, r3); |
4766 __ LoadSmiLiteral(r3, Smi::FromInt(count_value)); | 4853 __ LoadSmiLiteral(r3, Smi::FromInt(count_value)); |
4767 | 4854 |
4768 // Record position before stub call. | 4855 // Record position before stub call. |
4769 SetSourcePosition(expr->position()); | 4856 SetSourcePosition(expr->position()); |
4770 | 4857 |
4771 Handle<Code> code = | 4858 Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code(); |
4772 CodeFactory::BinaryOpIC(isolate(), Token::ADD, NO_OVERWRITE).code(); | |
4773 CallIC(code, expr->CountBinOpFeedbackId()); | 4859 CallIC(code, expr->CountBinOpFeedbackId()); |
4774 patch_site.EmitPatchInfo(); | 4860 patch_site.EmitPatchInfo(); |
4775 __ bind(&done); | 4861 __ bind(&done); |
4776 | 4862 |
4777 // Store the value returned in r3. | 4863 // Store the value returned in r3. |
4778 switch (assign_type) { | 4864 switch (assign_type) { |
4779 case VARIABLE: | 4865 case VARIABLE: |
4780 if (expr->is_postfix()) { | 4866 if (expr->is_postfix()) { |
4781 { | 4867 { |
4782 EffectContext context(this); | 4868 EffectContext context(this); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4831 } | 4917 } |
4832 } else { | 4918 } else { |
4833 context()->Plug(r3); | 4919 context()->Plug(r3); |
4834 } | 4920 } |
4835 break; | 4921 break; |
4836 } | 4922 } |
4837 case KEYED_PROPERTY: { | 4923 case KEYED_PROPERTY: { |
4838 __ Pop(StoreDescriptor::ReceiverRegister(), | 4924 __ Pop(StoreDescriptor::ReceiverRegister(), |
4839 StoreDescriptor::NameRegister()); | 4925 StoreDescriptor::NameRegister()); |
4840 Handle<Code> ic = | 4926 Handle<Code> ic = |
4841 CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); | 4927 CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); |
4842 CallIC(ic, expr->CountStoreFeedbackId()); | 4928 CallIC(ic, expr->CountStoreFeedbackId()); |
4843 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4929 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
4844 if (expr->is_postfix()) { | 4930 if (expr->is_postfix()) { |
4845 if (!context()->IsEffect()) { | 4931 if (!context()->IsEffect()) { |
4846 context()->PlugTOS(); | 4932 context()->PlugTOS(); |
4847 } | 4933 } |
4848 } else { | 4934 } else { |
4849 context()->Plug(r3); | 4935 context()->Plug(r3); |
4850 } | 4936 } |
4851 break; | 4937 break; |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5285 return ON_STACK_REPLACEMENT; | 5371 return ON_STACK_REPLACEMENT; |
5286 } | 5372 } |
5287 | 5373 |
5288 DCHECK(interrupt_address == | 5374 DCHECK(interrupt_address == |
5289 isolate->builtins()->OsrAfterStackCheck()->entry()); | 5375 isolate->builtins()->OsrAfterStackCheck()->entry()); |
5290 return OSR_AFTER_STACK_CHECK; | 5376 return OSR_AFTER_STACK_CHECK; |
5291 } | 5377 } |
5292 } | 5378 } |
5293 } // namespace v8::internal | 5379 } // namespace v8::internal |
5294 #endif // V8_TARGET_ARCH_PPC | 5380 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |