1.1 --- a/src/BytecodeCompiler.cpp Sat Sep 15 13:32:01 2012 -0700
1.2 +++ b/src/BytecodeCompiler.cpp Sat Sep 15 17:39:45 2012 -0700
1.3 @@ -199,10 +199,18 @@
1.4 __ pop();
1.5 }
1.6
1.7 +static inline bool
1.8 +IsCompositeValueType(Type *type)
1.9 +{
1.10 + return type->isStruct() ||
1.11 + (type->isArray() && type->isFixedLength());
1.12 +}
1.13 +
1.14 void
1.15 BytecodeCompiler::visit(Assignment *node)
1.16 {
1.17 - Local<Type> type(zone_, node->expression()->type());
1.18 + Local<Type> left(zone_, node->type());
1.19 + Local<Type> right(zone_, node->expression()->type());
1.20
1.21 // The first step is three sub-steps:
1.22 //
1.23 @@ -215,13 +223,12 @@
1.24 NameProxy *proxy = node->lvalue()->toNameProxy();
1.25 Variable *var = proxy->binding()->toVariable();
1.26
1.27 - // Bind.
1.28 - if (var->type()->isReference() ||
1.29 - var->type()->isArray() ||
1.30 - var->type()->isStruct())
1.31 - {
1.32 + // We need to fetch the variable under the following circumstances:
1.33 + // (1) The variable is a reference, since we'll store into the ref.
1.34 + // (2) The variable is a fixed array, since we need to copy into it.
1.35 + // (3) The variable is a struct, since we need to copy into it.
1.36 + if (var->type()->isReference() || IsCompositeValueType(var->type()))
1.37 __ get(var);
1.38 - }
1.39
1.40 // Get the value if needed.
1.41 if (node->token() != TOK_ASSIGN) {
1.42 @@ -247,8 +254,8 @@
1.43 if (node->token() != TOK_ASSIGN)
1.44 __ dup();
1.45
1.46 - if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
1.47 - __ getfield(expr->fieldIndex(), expr->type());
1.48 + if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
1.49 + __ getfield(expr->fieldIndex(), left);
1.50 } else {
1.51 IndexExpression *index = node->lvalue()->toIndexExpression();
1.52 __ note_position(index->pos());
1.53 @@ -259,14 +266,14 @@
1.54 if (node->token() != TOK_ASSIGN)
1.55 __ dup2();
1.56
1.57 - if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
1.58 - __ getelem(index->type());
1.59 + if (node->token() != TOK_ASSIGN || IsCompositeValueType(left))
1.60 + __ getelem(left);
1.61 }
1.62
1.63 if (node->token() == TOK_ASSIGN) {
1.64 node->expression()->accept(this);
1.65 } else {
1.66 - visitForALU(node->type(), node->expression());
1.67 + visitForALU(left, node->expression());
1.68
1.69 TokenKind alu = TokenKind(int(node->token()) - (TOK_ASSIGN_ADD - TOK_PLUS));
1.70 __ note_position(node->pos());
1.71 @@ -274,14 +281,16 @@
1.72 }
1.73
1.74 // Emit the store.
1.75 - if (type->isArray()) {
1.76 - // Unlike references, which can only be computed from a NamePRoxy,
1.77 - // arrays can be computed from multiple lvalue types.
1.78 + if (left->isArray() && left->isFixedLength()) {
1.79 + // (x = y) returns the left-hand side; if |x| is a fixed-length array,
1.80 + // then |y| is as well, and we perform a deep copy.
1.81 + assert(right->isFixedLength());
1.82 __ note_position(node->pos());
1.83 __ copyarray();
1.84 - } else if (type->isStruct()) {
1.85 + } else if (left->isStruct()) {
1.86 // Structs have value semantics, so emit a full copy. We don't break
1.87 // this down into u-ops, to avoid unnecessary bytecode explosion.
1.88 + assert(right->isStruct());
1.89 __ note_position(node->pos());
1.90 __ copystruct();
1.91 } else if (node->lvalue()->isNameProxy()) {
1.92 @@ -296,10 +305,9 @@
1.93 __ set(var);
1.94 } else if (node->lvalue()->isFieldExpression()) {
1.95 FieldExpression *expr = node->lvalue()->toFieldExpression();
1.96 - __ setfield(expr->fieldIndex(), expr->type());
1.97 + __ setfield(expr->fieldIndex(), left);
1.98 } else {
1.99 - IndexExpression *index = node->lvalue()->toIndexExpression();
1.100 - __ setelem(index->type());
1.101 + __ setelem(left);
1.102 }
1.103 }
1.104