Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index b051bd9bbb173e4070f6932d525e789f8ae96b97..2b80467bf91119a3bdfa83597b8a7c166ba47abc 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -1149,7 +1149,91 @@ void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { |
- UNIMPLEMENTED(); |
+ DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); |
+ |
+ // Left-hand side can only be a property, a global or a variable slot. |
+ Property* property = expr->expression()->AsProperty(); |
+ LhsKind assign_type = Property::GetAssignType(property); |
+ |
+ // TODO(rmcilroy): Set is_postfix to false if visiting for effect. |
+ bool is_postfix = expr->is_postfix(); |
+ |
+ // Evaluate LHS expression and get old value. |
+ TemporaryRegisterScope temporary_register_scope(builder()); |
+ Register obj, key, old_value; |
+ switch (assign_type) { |
+ case VARIABLE: { |
+ VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
+ VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
+ break; |
+ } |
+ case NAMED_PROPERTY: { |
+ obj = temporary_register_scope.NewRegister(); |
+ key = temporary_register_scope.NewRegister(); |
+ FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
+ Visit(property->obj()); |
+ builder() |
+ ->StoreAccumulatorInRegister(obj) |
+ .LoadLiteral(property->key()->AsLiteral()->AsPropertyName()) |
+ .StoreAccumulatorInRegister(key) |
+ .LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
+ break; |
+ } |
+ case KEYED_PROPERTY: { |
+ obj = temporary_register_scope.NewRegister(); |
+ key = temporary_register_scope.NewRegister(); |
+ FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
+ Visit(property->obj()); |
+ builder()->StoreAccumulatorInRegister(obj); |
+ Visit(property->key()); |
+ builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( |
+ obj, feedback_index(slot), language_mode()); |
+ break; |
+ } |
+ case NAMED_SUPER_PROPERTY: |
+ case KEYED_SUPER_PROPERTY: |
+ UNIMPLEMENTED(); |
+ } |
+ |
+ // Convert old value into a number. |
+ if (!is_strong(language_mode())) { |
+ builder()->CastAccumulatorToNumber(); |
+ } |
+ |
+ // Save result for postfix expressions. |
+ if (is_postfix) { |
+ old_value = temporary_register_scope.NewRegister(); |
+ builder()->StoreAccumulatorInRegister(old_value); |
+ } |
+ |
+ // Perform +1/-1 operation. |
+ builder()->CountOperation(expr->binary_op(), language_mode_strength()); |
+ |
+ // Store the value. |
+ FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
+ switch (assign_type) { |
+ case VARIABLE: { |
+ Variable* variable = expr->expression()->AsVariableProxy()->var(); |
+ VisitVariableAssignment(variable, feedback_slot); |
+ break; |
+ } |
+ case NAMED_PROPERTY: { |
+ builder()->StoreNamedProperty(obj, key, feedback_index(feedback_slot), |
+ language_mode()); |
+ break; |
+ } |
+ case KEYED_PROPERTY: { |
+ builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot), |
+ language_mode()); |
+ break; |
+ } |
+ case NAMED_SUPER_PROPERTY: |
+ case KEYED_SUPER_PROPERTY: |
+ UNIMPLEMENTED(); |
+ } |
+ |
+ // Restore old value for postfix expressions. |
+ if (is_postfix) builder()->LoadAccumulatorWithRegister(old_value); |
} |